', self.r.text):
self.restricted_ip = True
- self.write_warning('eRepublik has blacklisted IP. Limited functionality!', )
+ self.write_warning(
+ "eRepublik has blacklisted IP. Limited functionality!",
+ )
self.logged_in = True
def _errors_in_response(self, response: Response):
try:
j = response.json()
- if j['error'] and j['message'] == 'Too many requests':
- self.write_warning('Made too many requests! Sleeping for 30 seconds.')
+ if j["error"] and j["message"] == "Too many requests":
+ self.write_warning("Made too many requests! Sleeping for 30 seconds.")
self.sleep(30)
except (utils.json.JSONDecodeError, KeyError, TypeError):
pass
if response.status_code >= 400:
self.r = response
- if '
Attention Required! | Cloudflare' in response.text:
- self.write_warning('Cloudflare blocked request! You must inject valid CloudFlare cookie!')
- raise classes.CloudFlareSessionError(f"CloudFlare session error!", response)
- if response.text == 'Please verify your account.' or response.text == 'Forbidden':
+ if "
Attention Required! | Cloudflare" in response.text:
+ self.write_warning("Cloudflare blocked request! You must inject valid CloudFlare cookie!")
+ raise classes.CloudFlareSessionError("CloudFlare session error!", response)
+ if response.text == "Please verify your account." or response.text == "Forbidden":
self.do_captcha_challenge()
- raise classes.CaptchaSessionError(f"CaptchaSession has expired!", response)
+ raise classes.CaptchaSessionError("CaptchaSession has expired!", response)
elif response.status_code >= 500:
if self.restricted_ip:
self._req.cookies.clear()
return True
- self.write_warning('eRepublik servers are having internal troubles. Sleeping for 1 minutes')
+ self.write_warning("eRepublik servers are having internal troubles. Sleeping for 1 minutes")
self.sleep(1 * 60)
else:
raise classes.ErepublikException(f"HTTP {response.status_code} error!")
- if re.search(r'Occasionally there are a couple of things which we need to check or to implement in order make '
- r'your experience in eRepublik more pleasant.
Don\'t worry about ongoing battles, timer '
- r'will be stopped during maintenance.', response.text):
- self.write_warning('eRepublik is having maintenance. Sleeping for 5 mi#nutes')
+ if re.search(
+ r"Occasionally there are a couple of things which we need to check or to implement in order make "
+ r"your experience in eRepublik more pleasant.
Don\'t worry about ongoing battles, timer "
+ r"will be stopped during maintenance.",
+ response.text,
+ ):
+ self.write_warning("eRepublik is having maintenance. Sleeping for 5 mi#nutes")
self.sleep(5 * 60)
return True
- elif re.search('We are experiencing some tehnical dificulties', response.text):
- self.write_warning('eRepublik is having technical difficulties. Sleeping for 5 minutes')
+ elif re.search("We are experiencing some tehnical dificulties", response.text):
+ self.write_warning("eRepublik is having technical difficulties. Sleeping for 5 minutes")
self.sleep(5 * 60)
return True
- return bool(re.search(r'body id="error"|Internal Server Error|'
- r'CSRF attack detected|meta http-equiv="refresh"|'
- r'not_authenticated', response.text))
+ return bool(
+ re.search(
+ r'body id="error"|Internal Server Error|' r'CSRF attack detected|meta http-equiv="refresh"|' r"not_authenticated",
+ response.text,
+ )
+ )
def _report_action(self, action: str, msg: str, **kwargs: Optional[Dict[str, Any]]):
- """ Report action to all available reporting channels
+ """Report action to all available reporting channels
:type action: str
:type msg: str
@@ -857,7 +906,7 @@ class BaseCitizen(access_points.CitizenAPI):
"""
kwargs = utils.json_loads(utils.json_dumps(kwargs or {}))
action = action[:32]
- if msg.startswith('Unable to'):
+ if msg.startswith("Unable to"):
self.write_warning(msg)
else:
self.write_log(msg)
@@ -881,8 +930,8 @@ class CitizenAnniversary(BaseCitizen):
return self._post_map_rewards_claim(node_id, extra)
def speedup_map_quest_node(self, node_id: int):
- node = self.get_anniversary_quest_data().get('cities', {}).get(str(node_id), {})
- return self._post_map_rewards_speedup(node_id, node.get('skipCost', 0))
+ node = self.get_anniversary_quest_data().get("cities", {}).get(str(node_id), {})
+ return self._post_map_rewards_speedup(node_id, node.get("skipCost", 0))
def spin_wheel_of_fortune(self, max_cost=0, spin_count=0):
if not self.config.spin_wheel_of_fortune:
@@ -890,32 +939,32 @@ class CitizenAnniversary(BaseCitizen):
return
def _write_spin_data(cost: int, prize: str):
- self._report_action('WHEEL_SPIN', f"Cost: {cost:4d} | Currency left: {self.details.cc:,} | Prize: {prize}")
+ self._report_action("WHEEL_SPIN", f"Cost: {cost:4d} | Currency left: {self.details.cc:,} | Prize: {prize}")
if not self.wheel_of_fortune:
self.update_citizen_info()
base = self._post_main_wheel_of_fortune_build().json()
- current_cost = 0 if base.get('progress').get('free_spin') else base.get('cost')
- current_count = base.get('progress').get('spins')
- prizes = base.get('prizes')
+ current_cost = 0 if base.get("progress").get("free_spin") else base.get("cost")
+ current_count = base.get("progress").get("spins")
+ prizes = base.get("prizes")
if not max_cost and not spin_count:
r = self._post_main_wheel_of_fortune_spin(current_cost).json()
- _write_spin_data(current_cost, prizes.get('prizes').get(str(r.get('result'))).get('tooltip'))
+ _write_spin_data(current_cost, prizes.get("prizes").get(str(r.get("result"))).get("tooltip"))
else:
while max_cost >= current_cost if max_cost else spin_count >= current_count if spin_count else False:
r = self._spin_wheel_of_loosing(current_cost)
current_count += 1
- prize_name = prizes.get('prizes').get(str(r.get('result'))).get('tooltip')
- if r.get('result') == 7:
+ prize_name = prizes.get("prizes").get(str(r.get("result"))).get("tooltip")
+ if r.get("result") == 7:
prize_name += f" - {prizes.get('jackpot').get(str(r.get('jackpot'))).get('tooltip')}"
_write_spin_data(current_cost, prize_name)
- current_cost = r.get('cost')
- if r.get('jackpot', 0) == 3:
+ current_cost = r.get("cost")
+ if r.get("jackpot", 0) == 3:
return
def _spin_wheel_of_loosing(self, current_cost: int) -> Dict[str, Any]:
r = self._post_main_wheel_of_fortune_spin(current_cost).json()
- self.details.cc = float(Decimal(r.get('account')))
+ self.details.cc = float(Decimal(r.get("account")))
return r
@@ -926,11 +975,11 @@ class CitizenTravel(BaseCitizen):
def _travel(self, country: constants.Country, region_id: int = 0) -> bool:
r_json = super()._travel(country, region_id).json()
- if not bool(r_json.get('error')):
+ if not bool(r_json.get("error")):
self._update_citizen_location(country, region_id)
return True
else:
- if 'Travelling too fast.' in r_json.get('message'):
+ if "Travelling too fast." in r_json.get("message"):
self.sleep(1)
return self._travel(country, region_id)
return False
@@ -940,8 +989,8 @@ class CitizenTravel(BaseCitizen):
regs = []
if regions:
for region in regions.values():
- if region['countryId'] == country.id: # Is not occupied by other country
- regs.append((region['id'], region['distanceInKm']))
+ if region["countryId"] == country.id: # Is not occupied by other country
+ regs.append((region["id"], region["distanceInKm"]))
if regs:
return min(regs, key=lambda _: int(_[1]))[0]
else:
@@ -952,67 +1001,67 @@ class CitizenTravel(BaseCitizen):
res_r = self.details.residence_region
if self.details.residence_country and res_r and not res_r == self.details.current_region:
if self._travel(self.details.residence_country, self.details.residence_region):
- self._report_action('TRAVEL', 'Traveled to residence')
+ self._report_action("TRAVEL", "Traveled to residence")
return True
else:
- self._report_action('TRAVEL', 'Unable to travel to residence!')
+ self._report_action("TRAVEL", "Unable to travel to residence!")
return False
return True
def travel_to_region(self, region_id: int) -> bool:
data = self._post_main_travel_data(region_id=region_id).json()
- if data.get('alreadyInRegion'):
+ if data.get("alreadyInRegion"):
return True
else:
country = None
- for country_data in data.get('countries').values():
- if region_id in country_data.get('regions'):
- country = constants.COUNTRIES[country_data.get('id')]
+ for country_data in data.get("countries").values():
+ if region_id in country_data.get("regions"):
+ country = constants.COUNTRIES[country_data.get("id")]
break
if country is None:
- raise classes.ErepublikException('Region not found!')
+ raise classes.ErepublikException("Region not found!")
if self._travel(country, region_id):
- self._report_action('TRAVEL', 'Traveled to region')
+ self._report_action("TRAVEL", "Traveled to region")
return True
else:
- self._report_action('TRAVEL', 'Unable to travel to region!')
+ self._report_action("TRAVEL", "Unable to travel to region!")
return False
def travel_to_country(self, country: constants.Country) -> bool:
- data = self._post_main_travel_data(countryId=country.id, check='getCountryRegions').json()
+ data = self._post_main_travel_data(countryId=country.id, check="getCountryRegions").json()
regs = []
- if data.get('regions'):
- for region in data.get('regions').values():
- if region['countryId'] == country: # Is not occupied by other country
- regs.append((region['id'], region['distanceInKm']))
+ if data.get("regions"):
+ for region in data.get("regions").values():
+ if region["countryId"] == country: # Is not occupied by other country
+ regs.append((region["id"], region["distanceInKm"]))
if regs:
region_id = min(regs, key=lambda _: int(_[1]))[0]
if self._travel(country, region_id):
- self._report_action('TRAVEL', f"Traveled to {country.name}")
+ self._report_action("TRAVEL", f"Traveled to {country.name}")
return True
else:
- self._report_action('TRAVEL', f"Unable to travel to {country.name}!")
+ self._report_action("TRAVEL", f"Unable to travel to {country.name}!")
return False
def travel_to_holding(self, holding: classes.Holding) -> bool:
data = self._post_main_travel_data(holdingId=holding.id).json()
- if data.get('alreadyInRegion'):
+ if data.get("alreadyInRegion"):
return True
else:
- country = constants.COUNTRIES[data.get('preselectCountryId')]
- region_id = data.get('preselectRegionId')
+ country = constants.COUNTRIES[data.get("preselectCountryId")]
+ region_id = data.get("preselectRegionId")
if self._travel(country, region_id):
- self._report_action('TRAVEL', f"Traveled to {holding}")
+ self._report_action("TRAVEL", f"Traveled to {holding}")
return True
else:
- self._report_action('TRAVEL', f"Unable to travel to {holding}!")
+ self._report_action("TRAVEL", f"Unable to travel to {holding}!")
def travel_to_battle(self, battle: classes.Battle, allowed_countries: List[constants.Country]) -> bool:
data = self.get_travel_regions(battle=battle)
@@ -1021,32 +1070,36 @@ class CitizenTravel(BaseCitizen):
countries: Dict[int, constants.Country] = {c.id: c for c in allowed_countries}
if data:
for region in data.values():
- if region['countryId'] in countries: # Is not occupied by other country
- regs.append((region['distanceInKm'], region['id'], countries[region['countryId']]))
+ if region["countryId"] in countries: # Is not occupied by other country
+ regs.append((region["distanceInKm"], region["id"], countries[region["countryId"]]))
if regs:
reg = min(regs, key=lambda _: int(_[0]))
region_id = reg[1]
country = reg[2]
if self._travel(country, region_id):
- self._report_action('TRAVEL', f"Traveled to {battle}")
+ self._report_action("TRAVEL", f"Traveled to {battle}")
return True
else:
- self._report_action('TRAVEL', f"Unable to travel to {battle}!")
+ self._report_action("TRAVEL", f"Unable to travel to {battle}!")
return False
def get_travel_regions(
self, holding: classes.Holding = None, battle: classes.Battle = None, country: constants.Country = None
) -> Union[List[Any], Dict[str, Dict[str, Any]]]:
- return self._post_main_travel_data(
- holdingId=holding.id if holding else 0,
- battleId=battle.id if battle else 0,
- countryId=country.id if country else 0
- ).json().get('regions', [])
+ return (
+ self._post_main_travel_data(
+ holdingId=holding.id if holding else 0, battleId=battle.id if battle else 0, countryId=country.id if country else 0
+ )
+ .json()
+ .get("regions", [])
+ )
def get_travel_countries(self) -> Set[constants.Country]:
- warnings.simplefilter('always')
- warnings.warn('CitizenTravel.get_travel_countries() are being deprecated, '
- 'please use BaseCitizen.get_countries_with_regions()', DeprecationWarning)
+ warnings.simplefilter("always")
+ warnings.warn(
+ "CitizenTravel.get_travel_countries() are being deprecated, " "please use BaseCitizen.get_countries_with_regions()",
+ DeprecationWarning,
+ )
return self.get_countries_with_regions()
@@ -1059,8 +1112,8 @@ class CitizenCompanies(BaseCitizen):
if work_units_needed:
if work_units_needed <= self.my_companies.work_units:
- response = self._post_economy_work('production', employ=employee_companies).json()
- self.reporter.report_action('WORK_EMPLOYEES', response, response.get('status', False))
+ response = self._post_economy_work("production", employ=employee_companies).json()
+ self.reporter.report_action("WORK_EMPLOYEES", response, response.get("status", False))
self.update_companies()
ret = bool(self.my_companies.get_employable_factories())
@@ -1073,14 +1126,14 @@ class CitizenCompanies(BaseCitizen):
if self.restricted_ip:
return None
self.update_companies()
- data = {'action_type': 'production'}
+ data = {"action_type": "production"}
extra = {}
raw_factories = wam_holding.get_wam_companies(raw_factory=True)
fin_factories = wam_holding.get_wam_companies(raw_factory=False)
free_inventory = self.inventory.total - self.inventory.used
wam_list = raw_factories + fin_factories
- wam_list = wam_list[:self.energy.food_fights]
+ wam_list = wam_list[: self.energy.food_fights]
if int(free_inventory * 0.75) < self.my_companies.get_needed_inventory_usage(wam_list):
self.update_inventory()
@@ -1099,14 +1152,13 @@ class CitizenCompanies(BaseCitizen):
if sum(employ_factories.values()) > self.my_companies.work_units:
employ_factories = {}
- response = self._post_economy_work('production', wam=[c.id for c in wam_list],
- employ=employ_factories).json()
+ response = self._post_economy_work("production", wam=[c.id for c in wam_list], employ=employ_factories).json()
return response
def update_companies(self):
html = self._get_economy_my_companies().text
page_details = utils.json.loads(re.search(r"var pageDetails\s+= ({.*});", html).group(1))
- self.my_companies.work_units = int(page_details.get('total_works', 0))
+ self.my_companies.work_units = int(page_details.get("total_works", 0))
have_holdings = re.search(r"var holdingCompanies\s+= ({.*}});", html)
have_companies = re.search(r"var companies\s+= ({.*}});", html)
@@ -1132,8 +1184,8 @@ class CitizenCompanies(BaseCitizen):
"""
company_name = constants.INDUSTRIES[industry_id]
if building_type == 2:
- company_name = 'Storage'
- self.logger.info(f'{company_name} created!')
+ company_name = "Storage"
+ self.logger.info(f"{company_name} created!")
return self._post_economy_create_company(industry_id, building_type)
@@ -1146,14 +1198,14 @@ class CitizenEconomy(CitizenTravel):
currency = 62
resp = self._post_economy_exchange_retrieve(False, page, currency)
resp_data = resp.json()
- self.details.cc = float(resp_data.get('ecash').get('value'))
- self.details.gold = float(resp_data.get('gold').get('value'))
+ self.details.cc = float(resp_data.get("ecash").get("value"))
+ self.details.gold = float(resp_data.get("gold").get("value"))
def check_house_durability(self) -> Dict[int, datetime]:
ret = {}
inv = self.inventory
- for house_quality, active_house in inv.active.get('House', {}).items():
- till = utils.good_timedelta(self.now, timedelta(seconds=active_house['time_left']))
+ for house_quality, active_house in inv.active.get("House", {}).items():
+ till = utils.good_timedelta(self.now, timedelta(seconds=active_house["time_left"]))
ret.update({house_quality: till})
return ret
@@ -1161,30 +1213,32 @@ class CitizenEconomy(CitizenTravel):
original_region = self.details.current_country, self.details.current_region
ok_to_activate = False
inv = self.inventory
- if not inv.final.get('House', {}).get(q, {}):
- countries = [self.details.citizenship, ]
+ if not inv.final.get("House", {}).get(q, {}):
+ countries = [
+ self.details.citizenship,
+ ]
if self.details.current_country != self.details.citizenship:
countries.append(self.details.current_country)
- offers = [self.get_market_offers('House', q, country)[f"q{q}"] for country in countries]
+ offers = [self.get_market_offers("House", q, country)[f"q{q}"] for country in countries]
local_cheapest = sorted(offers, key=lambda o: o.price)[0]
- global_cheapest = self.get_market_offers('House', q)[f"q{q}"]
+ global_cheapest = self.get_market_offers("House", q)[f"q{q}"]
if global_cheapest.price + 2000 < local_cheapest.price:
if global_cheapest.price + 2000 < self.details.cc:
if self.travel_to_country(global_cheapest.country):
buy = self.buy_market_offer(global_cheapest, 1)
else:
- buy = dict(error=True, message='Unable to travel!')
+ buy = dict(error=True, message="Unable to travel!")
else:
- buy = dict(error=True, message='Not enough money to buy house!')
+ buy = dict(error=True, message="Not enough money to buy house!")
else:
if local_cheapest.price < self.details.cc:
buy = self.buy_market_offer(local_cheapest, 1)
else:
- buy = dict(error=True, message='Not enough money to buy house!')
+ buy = dict(error=True, message="Not enough money to buy house!")
if buy is None:
pass
- elif buy['error']:
+ elif buy["error"]:
self.write_warning(f'Unable to buy q{q} house! {buy["message"]}')
else:
ok_to_activate = True
@@ -1204,7 +1258,7 @@ class CitizenEconomy(CitizenTravel):
"""
house_durability = self.check_house_durability()
for q, active_till in house_durability.items():
- if utils.good_timedelta(active_till, - timedelta(hours=48)) <= self.now or forced:
+ if utils.good_timedelta(active_till, -timedelta(hours=48)) <= self.now or forced:
durability = self.buy_and_activate_house(q)
if durability:
house_durability = durability
@@ -1213,26 +1267,25 @@ class CitizenEconomy(CitizenTravel):
def activate_house(self, quality: int) -> bool:
r: Dict[str, Any] = self._post_economy_activate_house(quality).json()
self._update_inventory_data(r)
- if r.get('status') and not r.get('error'):
- house = self.inventory.active.get('House', {}).get(quality)
- time_left = timedelta(seconds=house['time_left'])
+ if r.get("status") and not r.get("error"):
+ house = self.inventory.active.get("House", {}).get(quality)
+ time_left = timedelta(seconds=house["time_left"])
active_until = utils.good_timedelta(self.now, time_left)
self._report_action(
- 'ACTIVATE_HOUSE',
- f"Activated {house['name']}. Expires at {active_until.strftime('%F %T')} (after {time_left})"
+ "ACTIVATE_HOUSE", f"Activated {house['name']}. Expires at {active_until.strftime('%F %T')} (after {time_left})"
)
return True
return False
def get_game_token_offers(self):
- r = self._post_economy_game_tokens_market('retrieve').json()
- return {v.get('id'): dict(amount=v.get('amount'), price=v.get('price')) for v in r.get('topOffers')}
+ r = self._post_economy_game_tokens_market("retrieve").json()
+ return {v.get("id"): dict(amount=v.get("amount"), price=v.get("price")) for v in r.get("topOffers")}
def fetch_organisation_account(self, org_id: int):
r = self._get_economy_citizen_accounts(org_id)
table = re.search(r'(
)', r.text, re.I | re.M | re.S)
if table:
- account = re.findall(r'>\s*(\d+.\d+)\s*', table.group(1))
+ account = re.findall(r">\s*(\d+.\d+)\s*", table.group(1))
if account:
return dict(gold=account[0], cc=account[1], ok=True)
@@ -1262,29 +1315,28 @@ class CitizenEconomy(CitizenTravel):
ret = []
for offer in self._get_economy_my_market_offers().json():
line = offer.copy()
- line.pop('icon', None)
+ line.pop("icon", None)
ret.append(line)
return ret
def delete_my_market_offer(self, offer_id: int) -> bool:
offers = self.get_my_market_offers()
for offer in offers:
- if offer['id'] == offer_id:
- industry = constants.INDUSTRIES[offer['industryId']]
- amount = offer['amount']
- q = offer['quality']
- price = offer['price']
- ret = self._post_economy_marketplace_actions('delete', offer_id=offer_id).json()
- if ret.get('error'):
- self._report_action('ECONOMY_DELETE_OFFER', f"Unable to delete offer: '{ret.get('message')}'",
- kwargs=offer)
+ if offer["id"] == offer_id:
+ industry = constants.INDUSTRIES[offer["industryId"]]
+ amount = offer["amount"]
+ q = offer["quality"]
+ price = offer["price"]
+ ret = self._post_economy_marketplace_actions("delete", offer_id=offer_id).json()
+ if ret.get("error"):
+ self._report_action("ECONOMY_DELETE_OFFER", f"Unable to delete offer: '{ret.get('message')}'", kwargs=offer)
else:
- self._report_action('ECONOMY_DELETE_OFFER',
- f"Removed offer for {amount} x {industry} q{q} for {price}cc/each",
- kwargs=offer)
- return not ret.get('error')
+ self._report_action(
+ "ECONOMY_DELETE_OFFER", f"Removed offer for {amount} x {industry} q{q} for {price}cc/each", kwargs=offer
+ )
+ return not ret.get("error")
else:
- self._report_action('ECONOMY_DELETE_OFFER', f"Unable to find offer id{offer_id}", kwargs={'offers': offers})
+ self._report_action("ECONOMY_DELETE_OFFER", f"Unable to find offer id{offer_id}", kwargs={"offers": offers})
return False
def post_market_offer(self, industry: int, quality: int, amount: int, price: float) -> bool:
@@ -1295,33 +1347,34 @@ class CitizenEconomy(CitizenTravel):
_inv_qlt = quality if industry in [1, 2, 3, 4, 23] else 0
final_kind = industry in [1, 2, 4, 23]
- items = (self.inventory.final if final_kind else self.inventory.raw).get(constants.INDUSTRIES[industry],
- {_inv_qlt: {'amount': 0}})
- if items[_inv_qlt]['amount'] < amount:
+ items = (self.inventory.final if final_kind else self.inventory.raw).get(constants.INDUSTRIES[industry], {_inv_qlt: {"amount": 0}})
+ if items[_inv_qlt]["amount"] < amount:
self.update_inventory()
- items = (self.inventory.final if final_kind else self.inventory.raw).get(constants.INDUSTRIES[industry],
- {_inv_qlt: {'amount': 0}})
- if items[_inv_qlt]['amount'] < amount:
- self._report_action('ECONOMY_SELL_PRODUCTS', 'Unable to sell! Not enough items in storage!',
- kwargs=dict(inventory=items[_inv_qlt], amount=amount))
+ items = (self.inventory.final if final_kind else self.inventory.raw).get(
+ constants.INDUSTRIES[industry], {_inv_qlt: {"amount": 0}}
+ )
+ if items[_inv_qlt]["amount"] < amount:
+ self._report_action(
+ "ECONOMY_SELL_PRODUCTS",
+ "Unable to sell! Not enough items in storage!",
+ kwargs=dict(inventory=items[_inv_qlt], amount=amount),
+ )
return False
- data = dict(country_id=self.details.citizenship.id, industry=industry, quality=quality, amount=amount,
- price=price, buy=False)
- ret = self._post_economy_marketplace_actions('sell', **data).json()
- message = (f"Posted market offer for {amount}q{quality} "
- f"{constants.INDUSTRIES[industry]} for price {price}cc")
- self._report_action('ECONOMY_SELL_PRODUCTS', message, kwargs=ret)
- return not bool(ret.get('error', True))
+ data = dict(country_id=self.details.citizenship.id, industry=industry, quality=quality, amount=amount, price=price, buy=False)
+ ret = self._post_economy_marketplace_actions("sell", **data).json()
+ message = f"Posted market offer for {amount}q{quality} " f"{constants.INDUSTRIES[industry]} for price {price}cc"
+ self._report_action("ECONOMY_SELL_PRODUCTS", message, kwargs=ret)
+ return not bool(ret.get("error", True))
def buy_from_market(self, offer: int, amount: int) -> Dict[str, Any]:
- ret = self._post_economy_marketplace_actions('buy', offer=offer, amount=amount)
+ ret = self._post_economy_marketplace_actions("buy", offer=offer, amount=amount)
json_ret = ret.json()
- if not json_ret.get('error', True):
- self.details.cc = ret.json()['currency']
- self.details.gold = ret.json()['gold']
- json_ret.pop('offerUpdate', None)
- self._report_action('BOUGHT_PRODUCTS', json_ret.get('message'), kwargs=json_ret)
+ if not json_ret.get("error", True):
+ self.details.cc = ret.json()["currency"]
+ self.details.gold = ret.json()["gold"]
+ json_ret.pop("offerUpdate", None)
+ self._report_action("BOUGHT_PRODUCTS", json_ret.get("message"), kwargs=json_ret)
return json_ret
def buy_market_offer(self, offer: classes.OfferItem, amount: int = None) -> Optional[Dict[str, Any]]:
@@ -1336,12 +1389,10 @@ class CitizenEconomy(CitizenTravel):
self.travel_to_residence()
return json_ret
- def get_market_offers(
- self, product_name: str, quality: int = None, country: constants.Country = None
- ) -> Dict[str, classes.OfferItem]:
- raw_short_names = dict(frm='foodRaw', wrm='weaponRaw', hrm='houseRaw', arm='airplaneRaw')
+ def get_market_offers(self, product_name: str, quality: int = None, country: constants.Country = None) -> Dict[str, classes.OfferItem]:
+ raw_short_names = dict(frm="foodRaw", wrm="weaponRaw", hrm="houseRaw", arm="airplaneRaw")
q1_industries = list(raw_short_names.values())
- q5_industries = ['house', 'aircraft', 'ticket']
+ q5_industries = ["house", "aircraft", "ticket"]
if product_name in raw_short_names:
quality = 1
product_name = raw_short_names[product_name]
@@ -1369,23 +1420,25 @@ class CitizenEconomy(CitizenTravel):
for country, q in product(*iterable):
r = self._post_economy_marketplace(country.id, constants.INDUSTRIES[product_name], q).json()
obj = offers[f"q{q}"]
- if not r.get('error', False):
- for offer in r['offers']:
- if (obj.price > float(offer['priceWithTaxes']) or (
- obj.price == float(offer['priceWithTaxes']) and obj.amount < int(offer['amount'])
- )):
+ if not r.get("error", False):
+ for offer in r["offers"]:
+ if obj.price > float(offer["priceWithTaxes"]) or (
+ obj.price == float(offer["priceWithTaxes"]) and obj.amount < int(offer["amount"])
+ ):
offers[f"q{q}"] = obj = classes.OfferItem(
- float(offer['priceWithTaxes']),
- constants.COUNTRIES[int(offer['country_id'])], int(offer['amount']),
- int(offer['id']), int(offer['citizen_id'])
+ float(offer["priceWithTaxes"]),
+ constants.COUNTRIES[int(offer["country_id"])],
+ int(offer["amount"]),
+ int(offer["id"]),
+ int(offer["citizen_id"]),
)
self.logger.debug(f"Scraped market in {self.now - start_dt}!")
return offers
def buy_food(self, energy_amount: int = 0):
- hp_needed = energy_amount if energy_amount else 48 * self.energy.interval * 10 - self.food['total']
- local_offers = self.get_market_offers('food', country=self.details.current_country)
+ hp_needed = energy_amount if energy_amount else 48 * self.energy.interval * 10 - self.food["total"]
+ local_offers = self.get_market_offers("food", country=self.details.current_country)
cheapest_q, cheapest = sorted(local_offers.items(), key=lambda v: v[1].price / constants.FOOD_ENERGY[v[0]])[0]
@@ -1395,33 +1448,41 @@ class CitizenEconomy(CitizenTravel):
amount = hp_needed // constants.FOOD_ENERGY[cheapest_q]
if amount * cheapest.price < self.details.cc:
- data = dict(offer=cheapest.offer_id, amount=amount, price=cheapest.price,
- cost=amount * cheapest.price, quality=cheapest_q,
- energy=amount * constants.FOOD_ENERGY[cheapest_q])
- self._report_action('BUY_FOOD', "", kwargs=data)
+ data = dict(
+ offer=cheapest.offer_id,
+ amount=amount,
+ price=cheapest.price,
+ cost=amount * cheapest.price,
+ quality=cheapest_q,
+ energy=amount * constants.FOOD_ENERGY[cheapest_q],
+ )
+ self._report_action("BUY_FOOD", "", kwargs=data)
self.buy_from_market(cheapest.offer_id, amount)
self.update_inventory()
else:
s = f"Don't have enough money! Needed: {amount * cheapest.price}cc, Have: {self.details.cc}cc"
self.write_warning(s)
- self._report_action('BUY_FOOD', s)
+ self._report_action("BUY_FOOD", s)
def get_monetary_offers(self, currency: int = 62) -> List[Dict[str, Union[int, float]]]:
if currency not in [1, 62]:
currency = 62
resp = self._post_economy_exchange_retrieve(False, 0, currency).json()
ret = []
- offers = re.findall(r"id='purchase_(\d+)' data-i18n='Buy for' data-currency='GOLD' "
- r"data-price='(\d+\.\d+)' data-max='(\d+\.\d+)' trigger='purchase'",
- resp['buy_mode'], re.M | re.I | re.S)
+ offers = re.findall(
+ r"id='purchase_(\d+)' data-i18n='Buy for' data-currency='GOLD' "
+ r"data-price='(\d+\.\d+)' data-max='(\d+\.\d+)' trigger='purchase'",
+ resp["buy_mode"],
+ re.M | re.I | re.S,
+ )
for offer_id, price, amount in offers:
ret.append(dict(offer_id=int(offer_id), price=float(price), amount=float(amount)))
- return sorted(ret, key=lambda o: (o['price'], -o['amount']))
+ return sorted(ret, key=lambda o: (o["price"], -o["amount"]))
def buy_monetary_market_offer(self, offer: int, amount: float, currency: int) -> int:
- """ Buy from monetary market
+ """Buy from monetary market
:param offer: offer id which should be bought
:type offer: int
@@ -1432,27 +1493,26 @@ class CitizenEconomy(CitizenTravel):
:return:
"""
response = self._post_economy_exchange_purchase(amount, currency, offer)
- self.details.cc = float(response.json().get('ecash').get('value'))
- self.details.gold = float(response.json().get('gold').get('value'))
- if response.json().get('error'):
- self._report_action('BUY_GOLD', 'Unable to buy gold!', kwargs=response.json())
+ self.details.cc = float(response.json().get("ecash").get("value"))
+ self.details.gold = float(response.json().get("gold").get("value"))
+ if response.json().get("error"):
+ self._report_action("BUY_GOLD", "Unable to buy gold!", kwargs=response.json())
return False
else:
- self._report_action('BUY_GOLD', f'New amount {self.details.cc}cc, {self.details.gold}g',
- kwargs=response.json())
+ self._report_action("BUY_GOLD", f"New amount {self.details.cc}cc, {self.details.gold}g", kwargs=response.json())
return True
def donate_money(self, citizen_id: int = 1620414, amount: float = 0.0, currency: int = 62) -> bool:
- """ currency: gold = 62, cc = 1 """
+ """currency: gold = 62, cc = 1"""
resp = self._post_economy_donate_money_action(citizen_id, amount, currency)
- r = re.search('You do not have enough money in your account to make this donation', resp.text)
+ r = re.search("You do not have enough money in your account to make this donation", resp.text)
success = not bool(r)
self.update_money()
- cur = 'g' if currency == 62 else 'cc'
+ cur = "g" if currency == 62 else "cc"
if success:
self.report_money_donation(citizen_id, amount, currency == 1)
else:
- self._report_action('DONATE_MONEY', f"Unable to donate {amount}{cur}!")
+ self._report_action("DONATE_MONEY", f"Unable to donate {amount}{cur}!")
return success
def donate_items(self, citizen_id: int = 1620414, amount: int = 0, industry_id: int = 1, quality: int = 1) -> int:
@@ -1462,27 +1522,23 @@ class CitizenEconomy(CitizenTravel):
self.write_log(f"Donate: {amount:4d}q{quality} {industry} to {citizen_id}")
response = self._post_economy_donate_items_action(citizen_id, amount, industry_id, quality)
if re.search(rf"Successfully transferred {amount} item\(s\) to", response.text):
- msg = (f"Successfully donated {amount}q{quality} {industry} "
- f"to citizen with id {citizen_id}!")
- self._report_action('DONATE_ITEMS', msg)
+ msg = f"Successfully donated {amount}q{quality} {industry} " f"to citizen with id {citizen_id}!"
+ self._report_action("DONATE_ITEMS", msg)
return amount
- elif re.search('You must wait 5 seconds before donating again', response.text):
- self.write_warning('Previous donation failed! Must wait at least 5 seconds before next donation!')
+ elif re.search("You must wait 5 seconds before donating again", response.text):
+ self.write_warning("Previous donation failed! Must wait at least 5 seconds before next donation!")
self.sleep(5)
return self.donate_items(citizen_id, int(amount), industry_id, quality)
else:
- if re.search(r'You do not have enough items in your inventory to make this donation', response.text):
- self._report_action('DONATE_ITEMS',
- f"Unable to donate {amount}q{quality} "
- f"{industry}, not enough left!")
+ if re.search(r"You do not have enough items in your inventory to make this donation", response.text):
+ self._report_action("DONATE_ITEMS", f"Unable to donate {amount}q{quality} " f"{industry}, not enough left!")
return 0
available = re.search(
- r'Cannot transfer the items because the user has only (\d+) free slots in (his|her) storage.',
- response.text
+ r"Cannot transfer the items because the user has only (\d+) free slots in (his|her) storage.", response.text
).group(1)
- self._report_action('DONATE_ITEMS',
- f'Unable to donate {amount}q{quality}{industry}'
- f', receiver has only {available} storage left!')
+ self._report_action(
+ "DONATE_ITEMS", f"Unable to donate {amount}q{quality}{industry}" f", receiver has only {available} storage left!"
+ )
self.sleep(5)
return self.donate_items(citizen_id, int(available), industry_id, quality)
@@ -1491,31 +1547,30 @@ class CitizenEconomy(CitizenTravel):
amount = int(amount)
if self.details.cc < amount or amount < 20:
return False
- data = dict(country=country.id, action='currency', value=amount)
- r = self._post_main_country_donate(country.id, 'currency', amount)
- if r.json().get('status') or not r.json().get('error'):
- self._report_action('CONTRIBUTE_CC', f'Contributed {amount}cc to {country}\'s treasury', kwargs=data)
+ data = dict(country=country.id, action="currency", value=amount)
+ r = self._post_main_country_donate(country.id, "currency", amount)
+ if r.json().get("status") or not r.json().get("error"):
+ self._report_action("CONTRIBUTE_CC", f"Contributed {amount}cc to {country}'s treasury", kwargs=data)
return True
else:
- self._report_action('CONTRIBUTE_CC', f"Unable to contribute {amount}cc to {country}'s"
- f' treasury', kwargs=r.json())
+ self._report_action("CONTRIBUTE_CC", f"Unable to contribute {amount}cc to {country}'s" f" treasury", kwargs=r.json())
return False
def contribute_food_to_country(self, amount, quality, country: constants.Country) -> bool:
self.update_inventory()
amount = amount // 1
- if self.food['q' + str(quality)] < amount or amount < 10:
+ if self.food["q" + str(quality)] < amount or amount < 10:
return False
- data = dict(country=country.id, action='food', value=amount, quality=quality)
- r = self._post_main_country_donate(country.id, 'currency', amount, quality)
+ data = dict(country=country.id, action="food", value=amount, quality=quality)
+ r = self._post_main_country_donate(country.id, "currency", amount, quality)
- if r.json().get('status') or not r.json().get('error'):
- self._report_action('CONTRIBUTE_FOOD', f"Contributed {amount}q{quality} food to "
- f"{country}'s treasury", kwargs=data)
+ if r.json().get("status") or not r.json().get("error"):
+ self._report_action("CONTRIBUTE_FOOD", f"Contributed {amount}q{quality} food to " f"{country}'s treasury", kwargs=data)
return True
else:
- self._report_action('CONTRIBUTE_FOOD', f"Unable to contribute {amount}q{quality} food to "
- f"{country}'s treasury", kwargs=r.json())
+ self._report_action(
+ "CONTRIBUTE_FOOD", f"Unable to contribute {amount}q{quality} food to " f"{country}'s treasury", kwargs=r.json()
+ )
return False
def contribute_gold_to_country(self, amount: int, country: constants.Country) -> bool:
@@ -1523,15 +1578,14 @@ class CitizenEconomy(CitizenTravel):
if self.details.cc < amount:
return False
- data = dict(country=country.id, action='gold', value=amount)
- r = self._post_main_country_donate(country.id, 'gold', amount)
+ data = dict(country=country.id, action="gold", value=amount)
+ r = self._post_main_country_donate(country.id, "gold", amount)
- if r.json().get('status') or not r.json().get('error'):
- self._report_action('CONTRIBUTE_GOLD', f"Contributed {amount}g to {country}'s treasury", kwargs=data)
+ if r.json().get("status") or not r.json().get("error"):
+ self._report_action("CONTRIBUTE_GOLD", f"Contributed {amount}g to {country}'s treasury", kwargs=data)
return True
else:
- self._report_action('CONTRIBUTE_GOLD', f"Unable to contribute {amount}g to {country}'s treasury",
- kwargs=r.json())
+ self._report_action("CONTRIBUTE_GOLD", f"Unable to contribute {amount}g to {country}'s treasury", kwargs=r.json())
return False
def report_money_donation(self, citizen_id: int, amount: float, is_currency: bool = True):
@@ -1563,12 +1617,11 @@ class CitizenMedia(BaseCitizen):
def endorse_article(self, article_id: int, amount: int) -> bool:
if amount in (5, 50, 100):
resp = self._post_main_donate_article(article_id, amount).json()
- if not bool(resp.get('error')):
- self._report_action('ARTICLE_ENDORSE', f"Endorsed article ({article_id}) with {amount}cc")
+ if not bool(resp.get("error")):
+ self._report_action("ARTICLE_ENDORSE", f"Endorsed article ({article_id}) with {amount}cc")
return True
else:
- self._report_action('ARTICLE_ENDORSE', f"Unable to endorse article ({article_id}) with {amount}cc",
- kwargs=resp)
+ self._report_action("ARTICLE_ENDORSE", f"Unable to endorse article ({article_id}) with {amount}cc", kwargs=resp)
return False
else:
return False
@@ -1576,31 +1629,39 @@ class CitizenMedia(BaseCitizen):
def vote_article(self, article_id: int) -> bool:
resp = self._post_main_vote_article(article_id).json()
- if not bool(resp.get('error')):
- self._report_action('ARTICLE_VOTE', f"Voted article {article_id}")
+ if not bool(resp.get("error")):
+ self._report_action("ARTICLE_VOTE", f"Voted article {article_id}")
return True
else:
- self._report_action('ARTICLE_VOTE', f"Unable to vote for article {article_id}", kwargs=resp)
+ self._report_action("ARTICLE_VOTE", f"Unable to vote for article {article_id}", kwargs=resp)
return False
def get_article_comments(self, article_id: int, page_id: int = 1) -> Dict[str, Any]:
return self._post_main_article_comments(article_id, page_id).json()
def write_article_comment(self, message: str, article_id: int, parent_id: int = None) -> Response:
- self._report_action('ARTICLE_COMMENT', f"Wrote a comment to article ({article_id})",
- kwargs=dict(msg=message, article_id=article_id, parent_id=parent_id))
+ self._report_action(
+ "ARTICLE_COMMENT",
+ f"Wrote a comment to article ({article_id})",
+ kwargs=dict(msg=message, article_id=article_id, parent_id=parent_id),
+ )
return self._post_main_article_comments_create(message, article_id, parent_id)
def publish_article(self, title: str, content: str, kind: int) -> int:
- kinds = {1: 'First steps in eRepublik', 2: 'Battle orders', 3: 'Warfare analysis',
- 4: 'Political debates and analysis', 5: 'Financial business',
- 6: 'Social interactions and entertainment'}
+ kinds = {
+ 1: "First steps in eRepublik",
+ 2: "Battle orders",
+ 3: "Warfare analysis",
+ 4: "Political debates and analysis",
+ 5: "Financial business",
+ 6: "Social interactions and entertainment",
+ }
if kind in kinds:
- data = {'title': title, 'content': content, 'country': self.details.citizenship.id, 'kind': kind}
+ data = {"title": title, "content": content, "country": self.details.citizenship.id, "kind": kind}
resp = self._post_main_write_article(title, content, self.details.citizenship.id, kind)
try:
article_id = int(resp.history[1].url.split("/")[-3])
- self._report_action('ARTICLE_PUBLISH', f"Published new article \"{title}\" ({article_id})", kwargs=data)
+ self._report_action("ARTICLE_PUBLISH", f'Published new article "{title}" ({article_id})', kwargs=data)
except: # noqa
article_id = 0
return article_id
@@ -1613,10 +1674,10 @@ class CitizenMedia(BaseCitizen):
def delete_article(self, article_id: int) -> NoReturn:
article_data = self.get_article(article_id)
- if article_data and article_data['articleData']['canDelete']:
- self._report_action('ARTICLE_DELETE',
- f"Attempting to delete article '{article_data['article']['title']}' (#{article_id})",
- kwargs=article_data)
+ if article_data and article_data["articleData"]["canDelete"]:
+ self._report_action(
+ "ARTICLE_DELETE", f"Attempting to delete article '{article_data['article']['title']}' (#{article_id})", kwargs=article_data
+ )
self._get_main_delete_article(article_id)
else:
self.write_warning(f"Unable to delete article (#{article_id})!")
@@ -1635,19 +1696,18 @@ class CitizenMilitary(CitizenTravel):
return d
def update_war_info(self):
- if self.__last_war_update_data and self.__last_war_update_data.get('last_updated',
- 0) + 30 > self.now.timestamp():
+ if self.__last_war_update_data and self.__last_war_update_data.get("last_updated", 0) + 30 > self.now.timestamp():
r_json = self.__last_war_update_data
else:
r_json = self._get_military_campaigns_json_list().json()
- if r_json.get('countries'):
+ if r_json.get("countries"):
if self.all_battles is None:
self.all_battles = {}
self.__last_war_update_data = r_json
- if r_json.get('battles'):
+ if r_json.get("battles"):
all_battles = {}
- for battle_data in r_json.get('battles', {}).values():
- all_battles[battle_data.get('id')] = classes.Battle(battle_data)
+ for battle_data in r_json.get("battles", {}).values():
+ all_battles[battle_data.get("id")] = classes.Battle(battle_data)
# old_all_battles = self.all_battles
self.all_battles = all_battles
# for battle in old_all_battles.values():
@@ -1656,7 +1716,7 @@ class CitizenMilitary(CitizenTravel):
def get_battle_for_war(self, war_id: int) -> Optional[classes.Battle]:
self.update_war_info()
war_info = self.get_war_status(war_id)
- return self.all_battles.get(war_info.get('battle_id'), None)
+ return self.all_battles.get(war_info.get("battle_id"), None)
def get_war_status(self, war_id: int) -> Dict[str, Union[bool, Dict[int, str]]]:
r = self._get_wars_show(war_id)
@@ -1666,13 +1726,15 @@ class CitizenMilitary(CitizenTravel):
if reg_re.findall(html):
ret.update(regions={}, can_attack=True)
for reg in reg_re.findall(html):
- ret['regions'].update({int(reg[0]): reg[1]})
- elif re.search(r'Join', html):
- battle_id = re.search(r'Join', html).group(1)
+ ret["regions"].update({int(reg[0]): reg[1]})
+ elif re.search(
+ r'Join', html
+ ):
+ battle_id = re.search(
+ r'Join', html
+ ).group(1)
ret.update(can_attack=False, battle_id=int(battle_id))
- elif re.search(r'This war is no longer active.', html):
+ elif re.search(r"This war is no longer active.", html):
ret.update(can_attack=False, ended=True)
else:
ret.update(can_attack=False)
@@ -1690,18 +1752,17 @@ class CitizenMilitary(CitizenTravel):
if not division.is_air:
for weapon in available_weapons:
try:
- if weapon['weaponQuantity'] > 30 and weapon['weaponInfluence'] > weapon_damage:
- weapon_quality = int(weapon['weaponId'])
- weapon_damage = weapon['weaponInfluence']
+ if weapon["weaponQuantity"] > 30 and weapon["weaponInfluence"] > weapon_damage:
+ weapon_quality = int(weapon["weaponId"])
+ weapon_damage = weapon["weaponInfluence"]
except ValueError:
pass
return self.change_weapon(battle, weapon_quality, division)
def change_weapon(self, battle: classes.Battle, quality: int, battle_zone: classes.BattleDivision) -> int:
r = self._post_military_change_weapon(battle.id, battle_zone.id, quality)
- influence = r.json().get('weaponInfluence')
- self._report_action('MILITARY_WEAPON', f"Switched to q{quality} weapon,"
- f" new influence {influence}", kwargs=r.json())
+ influence = r.json().get("weaponInfluence")
+ self._report_action("MILITARY_WEAPON", f"Switched to q{quality} weapon," f" new influence {influence}", kwargs=r.json())
return influence
def sorted_battles(self, sort_by_time: bool = True, only_tp=False) -> List[classes.Battle]:
@@ -1724,12 +1785,12 @@ class CitizenMilitary(CitizenTravel):
battle_list = sorted(self.all_battles.values(), key=lambda b: b.id)
contribution_json = self._get_military_campaigns_json_citizen().json()
- contributions: List[Dict[str, int]] = contribution_json.get('contributions') or []
- contributions.sort(key=lambda b: -b.get('damage'))
+ contributions: List[Dict[str, int]] = contribution_json.get("contributions") or []
+ contributions.sort(key=lambda b: -b.get("damage"))
for contribution_battle in contributions:
- if contribution_battle.get('battle_id') and contribution_battle.get('battle_id') in self.all_battles:
- ret_battles.append(self.all_battles[contribution_battle.get('battle_id')])
+ if contribution_battle.get("battle_id") and contribution_battle.get("battle_id") in self.all_battles:
+ ret_battles.append(self.all_battles[contribution_battle.get("battle_id")])
for battle in battle_list:
battle_sides = [battle.invader.country, battle.defender.country]
@@ -1796,7 +1857,7 @@ class CitizenMilitary(CitizenTravel):
if not medal:
air_divs.append((0, division))
else:
- air_divs.append((medal.get('1').get('raw_value'), division))
+ air_divs.append((medal.get("1").get("raw_value"), division))
elif not division.is_air and self.config.ground:
if not division.div == self.division and not check_maverick:
continue
@@ -1805,19 +1866,17 @@ class CitizenMilitary(CitizenTravel):
if not medal:
ground_divs.append((0, division))
else:
- ground_divs.append((medal.get('1').get('raw_value'), division))
+ ground_divs.append((medal.get("1").get("raw_value"), division))
air_divs.sort(key=lambda z: (z[0], z[1].battle.start))
ground_divs.sort(key=lambda z: (z[0], z[1].battle.start))
- return {'air': air_divs, 'ground': ground_divs}
+ return {"air": air_divs, "ground": ground_divs}
@property
def has_battle_contribution(self):
- return bool(self.__last_war_update_data.get('citizen_contribution', []))
+ return bool(self.__last_war_update_data.get("citizen_contribution", []))
- def find_battle_to_fight(self, silent: bool = False) -> Tuple[
- classes.Battle, classes.BattleDivision, classes.BattleSide
- ]:
+ def find_battle_to_fight(self, silent: bool = False) -> Tuple[classes.Battle, classes.BattleDivision, classes.BattleSide]:
self.update_war_info()
for battle in self.sorted_battles(self.config.sort_battles_time):
if not isinstance(battle, classes.Battle):
@@ -1840,22 +1899,22 @@ class CitizenMilitary(CitizenTravel):
continue
if not battle_zone:
continue
- allies = battle.invader.deployed + battle.defender.deployed + [battle.invader.country,
- battle.defender.country]
+ allies = battle.invader.deployed + battle.defender.deployed + [battle.invader.country, battle.defender.country]
travel_needed = self.details.current_country not in allies
if battle.is_rw:
side = battle.defender if self.config.rw_def_side else battle.invader
else:
- defender_side = self.details.current_country in battle.defender.allies + [battle.defender.country, ]
+ defender_side = self.details.current_country in battle.defender.allies + [
+ battle.defender.country,
+ ]
side = battle.defender if defender_side else battle.invader
if not silent:
self.write_log(str(battle))
- travel = (self.config.travel_to_fight and self.should_travel_to_fight() or self.config.force_travel) \
- if travel_needed else True
+ travel = (self.config.travel_to_fight and self.should_travel_to_fight() or self.config.force_travel) if travel_needed else True
if not travel:
continue
@@ -1864,11 +1923,10 @@ class CitizenMilitary(CitizenTravel):
def find_battle_and_fight(self):
count = self.should_fight()[0]
if count:
- self.write_log('Checking for battles to fight in...')
+ self.write_log("Checking for battles to fight in...")
for battle, division, side in self.find_battle_to_fight():
- allies = battle.invader.deployed + battle.defender.deployed + [battle.invader.country,
- battle.defender.country]
+ allies = battle.invader.deployed + battle.defender.deployed + [battle.invader.country, battle.defender.country]
travel_needed = self.details.current_country not in allies
@@ -1884,8 +1942,14 @@ class CitizenMilitary(CitizenTravel):
self.travel_to_residence()
break
- def fight(self, battle: classes.Battle, division: classes.BattleDivision, side: classes.BattleSide = None,
- count: int = None, use_ebs: bool = False) -> Optional[int]:
+ def fight(
+ self,
+ battle: classes.Battle,
+ division: classes.BattleDivision,
+ side: classes.BattleSide = None,
+ count: int = None,
+ use_ebs: bool = False,
+ ) -> Optional[int]:
"""Fight in a battle.
Will auto activate booster and travel if allowed to do it.
@@ -1904,14 +1968,13 @@ class CitizenMilitary(CitizenTravel):
:rtype: int
"""
if self.restricted_ip:
- self.write_warning('Fighting is not allowed from restricted IP!')
- self._report_action('IP_BLACKLISTED', 'Fighting is not allowed from restricted IP!')
+ self.write_warning("Fighting is not allowed from restricted IP!")
+ self._report_action("IP_BLACKLISTED", "Fighting is not allowed from restricted IP!")
return 1
if not division.is_air and self.config.boosters:
self.activate_damage_booster(not division.is_air)
if side is None:
- side = battle.defender if self.details.citizenship in battle.defender.allies + [
- battle.defender.country] else battle.invader
+ side = battle.defender if self.details.citizenship in battle.defender.allies + [battle.defender.country] else battle.invader
if count is None:
count = self.should_fight()[0]
@@ -1939,13 +2002,15 @@ class CitizenMilitary(CitizenTravel):
self.sleep(count // 3) # TODO: connect to eRepublik's WS and get from there when deploy ends
energy_used = 0
if deployment_id:
- self.write_warning('If erepublik responds with HTTP 500 Internal Error, it is kind of ok, because deployment has not finished yet.')
+ self.write_warning(
+ "If erepublik responds with HTTP 500 Internal Error, it is kind of ok, because deployment has not finished yet."
+ )
deployment_data = self._post_military_fight_deploy_deploy_report_data(deployment_id).json()
- if not deployment_data.get('error'):
- data = deployment_data['data']
- total_damage = int(data['damage'].replace(',', ''))
- energy_used = int(data['energySpent'].replace(',', ''))
- self.details.pp += int(data['rewards']['prestigePoints'].replace(',', ''))
+ if not deployment_data.get("error"):
+ data = deployment_data["data"]
+ total_damage = int(data["damage"].replace(",", ""))
+ energy_used = int(data["energySpent"].replace(",", ""))
+ self.details.pp += int(data["rewards"]["prestigePoints"].replace(",", ""))
self.report_fighting(battle, not side.is_defender, division, total_damage, energy_used // 10)
return energy_used
@@ -1955,7 +2020,7 @@ class CitizenMilitary(CitizenTravel):
else:
response = self._post_military_fight_ground(battle.id, side.id, division.id)
- if 'Zone is not meant for ' in response.text:
+ if "Zone is not meant for " in response.text:
self.sleep(5)
return 0, 1, 0
try:
@@ -1965,54 +2030,54 @@ class CitizenMilitary(CitizenTravel):
hits = 0
damage = 0
err = False
- if r_json.get('error'):
- if r_json.get('message') == 'SHOOT_LOCKOUT':
+ if r_json.get("error"):
+ if r_json.get("message") == "SHOOT_LOCKOUT":
pass
- elif r_json.get('message') == 'NOT_ENOUGH_WEAPONS':
+ elif r_json.get("message") == "NOT_ENOUGH_WEAPONS":
self.set_default_weapon(battle, division)
- elif r_json.get('message') == "Cannot activate a zone with a non-native division":
- self.write_warning('Wrong division!!')
+ elif r_json.get("message") == "Cannot activate a zone with a non-native division":
+ self.write_warning("Wrong division!!")
return 0, 10, 0
- elif r_json.get('message') == 'ZONE_INACTIVE':
- self.write_warning('Wrong division!!')
+ elif r_json.get("message") == "ZONE_INACTIVE":
+ self.write_warning("Wrong division!!")
return 0, 10, 0
- elif r_json.get('message') == 'NON_BELLIGERENT':
+ elif r_json.get("message") == "NON_BELLIGERENT":
self.write_warning("Dictatorship/Liberation wars are not supported!")
return 0, 10, 0
- elif r_json.get('message') in ['FIGHT_DISABLED', 'DEPLOYMENT_MODE']:
- self._post_main_profile_update('options',
- params='{"optionName":"enable_web_deploy","optionValue":"off"}')
+ elif r_json.get("message") in ["FIGHT_DISABLED", "DEPLOYMENT_MODE"]:
+ self._post_main_profile_update("options", params='{"optionName":"enable_web_deploy","optionValue":"off"}')
self.set_default_weapon(battle, division)
else:
- if r_json.get('message') == 'UNKNOWN_SIDE':
+ if r_json.get("message") == "UNKNOWN_SIDE":
self._rw_choose_side(battle, side)
- elif r_json.get('message') == 'CHANGE_LOCATION':
+ elif r_json.get("message") == "CHANGE_LOCATION":
countries = [side.country] + side.deployed
self.travel_to_battle(battle, countries)
err = True
- elif r_json.get('message') == 'ENEMY_KILLED':
+ elif r_json.get("message") == "ENEMY_KILLED":
# Non-InfantryKit players
- if r_json['user']['earnedXp']:
- hits = r_json['user']['earnedXp']
+ if r_json["user"]["earnedXp"]:
+ hits = r_json["user"]["earnedXp"]
# InfantryKit player
# The almost always safe way (breaks on levelup hit)
- elif self.energy.energy >= r_json['details']['wellness']: # Haven't reached levelup
- hits = (self.energy.energy - r_json['details']['wellness']) // 10
+ elif self.energy.energy >= r_json["details"]["wellness"]: # Haven't reached levelup
+ hits = (self.energy.energy - r_json["details"]["wellness"]) // 10
else:
- hits = r_json['hits']
- if r_json['user']['epicBattle']:
- hits /= 1 + r_json['user']['epicBattle']
+ hits = r_json["hits"]
+ if r_json["user"]["epicBattle"]:
+ hits /= 1 + r_json["user"]["epicBattle"]
- self.energy.energy = r_json['details']['wellness']
- self.details.xp = int(r_json['details']['points'])
- damage = r_json['user']['givenDamage'] * (1.1 if r_json['oldEnemy']['isNatural'] else 1)
+ self.energy.energy = r_json["details"]["wellness"]
+ self.details.xp = int(r_json["details"]["points"])
+ damage = r_json["user"]["givenDamage"] * (1.1 if r_json["oldEnemy"]["isNatural"] else 1)
else:
err = True
return hits, err, damage
- def deploy_bomb(self, battle: classes.Battle, division: classes.BattleDivision, bomb_id: int, inv_side: bool,
- count: int = 1) -> Optional[int]:
+ def deploy_bomb(
+ self, battle: classes.Battle, division: classes.BattleDivision, bomb_id: int, inv_side: bool, count: int = 1
+ ) -> Optional[int]:
"""Deploy bombs in a battle for given side.
:param battle: Battle
@@ -2040,20 +2105,19 @@ class CitizenMilitary(CitizenTravel):
if self.details.current_country not in good_countries:
has_traveled = self.travel_to_battle(battle, good_countries)
else:
- involved = [battle.invader.country,
- battle.defender.country] + battle.invader.deployed + battle.defender.deployed
+ involved = [battle.invader.country, battle.defender.country] + battle.invader.deployed + battle.defender.deployed
if self.details.current_country not in involved:
count = 0
side = battle.invader if inv_side else battle.defender
errors = deployed_count = 0
while (not deployed_count == count) and errors < 10:
r = self._post_military_deploy_bomb(battle.id, division.id, side.id, bomb_id).json()
- if not r.get('error'):
+ if not r.get("error"):
deployed_count += 1
self.sleep(0.5)
- elif r.get('message') == 'LOCKED':
+ elif r.get("message") == "LOCKED":
self.sleep(0.5)
- elif r.get('message') == 'INVALID_BOMB':
+ elif r.get("message") == "INVALID_BOMB":
errors = 10
else:
errors += 1
@@ -2061,7 +2125,7 @@ class CitizenMilitary(CitizenTravel):
if has_traveled:
self.travel_to_residence()
- self._report_action('MILITARY_BOMB', f"Deployed {deployed_count} bombs in battle {battle.id}")
+ self._report_action("MILITARY_BOMB", f"Deployed {deployed_count} bombs in battle {battle.id}")
return deployed_count
def change_division(self, battle: classes.Battle, division: classes.BattleDivision, side: classes.BattleSide = None) -> bool:
@@ -2076,64 +2140,70 @@ class CitizenMilitary(CitizenTravel):
:return:
"""
resp = self._post_main_battlefield_change_division(battle.id, division.id, side.id if side else None)
- if resp.json().get('error'):
- self.write_warning(resp.json().get('message'))
+ if resp.json().get("error"):
+ self.write_warning(resp.json().get("message"))
return False
- self._report_action('MILITARY_DIV_SWITCH', f"Switched to d{division.div} in battle {battle.id}",
- kwargs=resp.json())
+ self._report_action("MILITARY_DIV_SWITCH", f"Switched to d{division.div} in battle {battle.id}", kwargs=resp.json())
return True
- def get_ground_hit_dmg_value(self, rang: int = None, strength: float = None, elite: bool = None, ne: bool = False,
- booster_50: bool = False, booster_100: bool = False, tp: bool = True) -> Decimal:
+ def get_ground_hit_dmg_value(
+ self,
+ rang: int = None,
+ strength: float = None,
+ elite: bool = None,
+ ne: bool = False,
+ booster_50: bool = False,
+ booster_100: bool = False,
+ tp: bool = True,
+ ) -> Decimal:
if not rang or not strength or elite is None:
r = self._get_main_citizen_profile_json(self.details.citizen_id).json()
if not rang:
- rang = r['military']['militaryData']['ground']['rankNumber']
+ rang = r["military"]["militaryData"]["ground"]["rankNumber"]
if not strength:
- strength = r['military']['militaryData']['ground']['strength']
+ strength = r["military"]["militaryData"]["ground"]["strength"]
if elite is None:
- elite = r['citizenAttributes']['level'] > 100
+ elite = r["citizenAttributes"]["level"] > 100
if ne:
tp = True
return utils.calculate_hit(strength, rang, tp, elite, ne, 50 if booster_50 else 100 if booster_100 else 0)
- def get_air_hit_dmg_value(self, rang: int = None, elite: bool = None, ne: bool = False,
- weapon: bool = False) -> Decimal:
+ def get_air_hit_dmg_value(self, rang: int = None, elite: bool = None, ne: bool = False, weapon: bool = False) -> Decimal:
if not rang or elite is None:
r = self._get_main_citizen_profile_json(self.details.citizen_id).json()
if not rang:
- rang = r['military']['militaryData']['aircraft']['rankNumber']
+ rang = r["military"]["militaryData"]["aircraft"]["rankNumber"]
if elite is None:
- elite = r['citizenAttributes']['level'] > 100
+ elite = r["citizenAttributes"]["level"] > 100
return utils.calculate_hit(0, rang, True, elite, ne, 0, 20 if weapon else 0)
def activate_damage_booster(self, ground: bool = True) -> int:
- kind = 'damage' if ground else 'aircraftDamage'
+ kind = "damage" if ground else "aircraftDamage"
if self.config.boosters and not self.get_active_damage_booster(ground):
booster: Optional[types.InvFinalItem] = None
for quality, data in sorted(self.inventory.boosters.get(kind, {}).items(), key=lambda x: x[0]):
for _duration, _booster in sorted(data.items(), key=lambda y: y[0]):
critical_amount = 2 if quality < 10 and ground else 10
- if _booster.get('amount') > critical_amount:
+ if _booster.get("amount") > critical_amount:
booster = _booster
break
break
if booster:
- kind = 'damage' if ground else 'air_damage'
- self._report_action('MILITARY_BOOSTER', f"Activated {booster['name']}")
- resp = self._post_economy_activate_booster(booster['quality'], booster['durability'], kind).json()
+ kind = "damage" if ground else "air_damage"
+ self._report_action("MILITARY_BOOSTER", f"Activated {booster['name']}")
+ resp = self._post_economy_activate_booster(booster["quality"], booster["durability"], kind).json()
self._update_inventory_data(resp)
return self.get_active_damage_booster(ground)
def get_active_damage_booster(self, ground: bool = True) -> int:
- kind = 'damage' if ground else 'aircraftDamage'
+ kind = "damage" if ground else "aircraftDamage"
boosters = self.inventory.active.get(kind, {})
quality = 0
for q, boost in boosters.items():
- if boost['quality'] * 10 > quality:
- quality = boost['quality'] * 10
+ if boost["quality"] * 10 > quality:
+ quality = boost["quality"] * 10
return quality
def get_active_ground_damage_booster(self) -> int:
@@ -2143,15 +2213,15 @@ class CitizenMilitary(CitizenTravel):
return self.get_active_damage_booster(False)
def activate_battle_effect(self, battle_id: int, kind: str) -> bool:
- self._report_action('MILITARY_BOOSTER', f'Activated {kind} booster')
+ self._report_action("MILITARY_BOOSTER", f"Activated {kind} booster")
resp = self._post_main_activate_battle_effect(battle_id, kind, self.details.citizen_id).json()
- return not resp.get('error')
+ return not resp.get("error")
def activate_pp_booster(self, pp_item: types.InvFinalItem) -> bool:
- self._report_action('MILITARY_BOOSTER', f'Activated {pp_item["name"]}')
- resp = self._post_economy_activate_booster(pp_item['quality'], pp_item['durability'], 'prestige_points').json()
+ self._report_action("MILITARY_BOOSTER", f'Activated {pp_item["name"]}')
+ resp = self._post_economy_activate_booster(pp_item["quality"], pp_item["durability"], "prestige_points").json()
self._update_inventory_data(resp)
- return pp_item.get('kind') in self.inventory.active
+ return pp_item.get("kind") in self.inventory.active
def _rw_choose_side(self, battle: classes.Battle, side: classes.BattleSide) -> Response:
return self._post_main_battlefield_travel(side.id, battle.id)
@@ -2171,23 +2241,23 @@ class CitizenMilitary(CitizenTravel):
return ret
def should_fight(self) -> Tuple[int, str, bool]:
- """ Checks if citizen should fight at this moment
+ """Checks if citizen should fight at this moment
:rtype: Tuple[int, str, bool]
"""
count = 0
force_fight = False
- msg = 'Fighting not allowed!'
+ msg = "Fighting not allowed!"
if not self.config.fight:
return count, msg, force_fight
# Do levelup
if self.is_levelup_reachable:
- msg = 'Level up'
+ msg = "Level up"
if self.should_do_levelup:
count = (self.energy.limit * 3) // 10
force_fight = True
else:
- self.write_log('Waiting for fully recovered energy before leveling up.')
+ self.write_log("Waiting for fully recovered energy before leveling up.")
# Levelup reachable
elif self.is_levelup_close:
@@ -2197,12 +2267,12 @@ class CitizenMilitary(CitizenTravel):
elif self.details.pp < 75:
count = 75 - self.details.pp
- msg = 'Obligatory fighting for at least 75pp'
+ msg = "Obligatory fighting for at least 75pp"
force_fight = True
elif self.config.continuous_fighting and self.has_battle_contribution:
count = self.energy.food_fights
- msg = 'Continuing to fight in previous battle'
+ msg = "Continuing to fight in previous battle"
# All-in (type = all-in and full ff)
elif self.config.all_in and self.energy.energy + self.energy.interval * 3 >= self.energy.limit:
@@ -2225,12 +2295,18 @@ class CitizenMilitary(CitizenTravel):
def get_battle_round_data(self, division: classes.BattleDivision) -> Tuple[Any, Any]:
battle = division.battle
- r = self._post_military_battle_console(battle.id, 'battleStatistics', 1,
- zoneId=battle.zone_id, round_id=battle.zone_id, division=division.div,
- battleZoneId=division.id, type='damage')
+ r = self._post_military_battle_console(
+ battle.id,
+ "battleStatistics",
+ 1,
+ zoneId=battle.zone_id,
+ round_id=battle.zone_id,
+ division=division.div,
+ battleZoneId=division.id,
+ type="damage",
+ )
r_json = r.json()
- return (r_json.get(str(battle.invader.id)).get('fighterData'),
- r_json.get(str(battle.defender.id)).get('fighterData'))
+ return (r_json.get(str(battle.invader.id)).get("fighterData"), r_json.get(str(battle.defender.id)).get("fighterData"))
def get_battle_division_stats(self, division: classes.BattleDivision) -> Dict[str, Any]:
battle = division.battle
@@ -2238,14 +2314,14 @@ class CitizenMilitary(CitizenTravel):
return r.json()
def get_division_max_hit(self, division: classes.BattleDivision) -> int:
- """ Returns max hit in division for current side (if not on either side returns 0)
+ """Returns max hit in division for current side (if not on either side returns 0)
:param division: BattleDivision for which to get max hit value
:type division: classes.BattleDivision
:return: max hit value
:rtype: int
"""
- return self.get_battle_division_stats(division).get('maxHit', -1)
+ return self.get_battle_division_stats(division).get("maxHit", -1)
def schedule_attack(self, war_id: int, region_id: int, region_name: str, at_time: datetime):
if at_time:
@@ -2262,58 +2338,58 @@ class CitizenMilitary(CitizenTravel):
r = self._get_wars_show(war_id)
html = r.text
last_battle_id = int(re.search(r'', html).group(1))
- console = self._post_military_battle_console(last_battle_id, 'warList', 1).json()
- battle = console.get('list')[0]
- return utils.localize_dt(datetime.strptime(battle.get('result').get('end'), "%Y-%m-%d %H:%M:%S"))
+ console = self._post_military_battle_console(last_battle_id, "warList", 1).json()
+ battle = console.get("list")[0]
+ return utils.localize_dt(datetime.strptime(battle.get("result").get("end"), "%Y-%m-%d %H:%M:%S"))
def launch_attack(self, war_id: int, region_id: int, region_name: str):
self._post_wars_attack_region(war_id, region_id, region_name)
- self._report_action('MILITARY_QUEUE_ATTACK', f"Battle for *{region_name}* queued")
+ self._report_action("MILITARY_QUEUE_ATTACK", f"Battle for *{region_name}* queued")
def get_country_mus(self, country: constants.Country) -> Dict[int, str]:
ret = {}
r = self._get_main_leaderboards_damage_rankings(country.id)
- for data in r.json()['mu_filter']:
- if data['id']:
- ret.update({data['id']: data['name']})
+ for data in r.json()["mu_filter"]:
+ if data["id"]:
+ ret.update({data["id"]: data["name"]})
r = self._get_main_leaderboards_damage_aircraft_rankings(country.id)
- for data in r.json()['mu_filter']:
- if data['id']:
- ret.update({data['id']: data['name']})
+ for data in r.json()["mu_filter"]:
+ if data["id"]:
+ ret.update({data["id"]: data["name"]})
return ret
def get_mu_members(self, mu_id: int) -> Dict[int, str]:
ret = {}
r = self._get_military_unit_data(mu_id)
- for page in range(int(r.json()['panelContents']['pages'])):
+ for page in range(int(r.json()["panelContents"]["pages"])):
r = self._get_military_unit_data(mu_id, currentPage=page + 1)
- for user in r.json()['panelContents']['members']:
- if not user['isDead']:
- ret.update({user['citizenId']: user['name']})
+ for user in r.json()["panelContents"]["members"]:
+ if not user["isDead"]:
+ ret.update({user["citizenId"]: user["name"]})
return ret
def get_citizen_weekly_daily_orders_done(self, citizen_id: int = None, weeks_ago: int = 0) -> int:
if citizen_id is None:
citizen_id = self.details.citizen_id
profile = self._get_main_citizen_profile_json(citizen_id).json()
- mu_id = profile.get('military', {}).get('militaryUnit', {}).get('id', 0)
+ mu_id = profile.get("military", {}).get("militaryUnit", {}).get("id", 0)
if mu_id:
- name = profile.get('citizen', {}).get('name')
- member = self._get_military_unit_data(mu_id, currentPage=1, panel='members', sortBy='dailyOrdersCompleted',
- weekFilter=f"week{weeks_ago}", search=name).json()
- return member.get('panelContents', {}).get('members', [{}])[0].get('dailyOrdersCompleted')
+ name = profile.get("citizen", {}).get("name")
+ member = self._get_military_unit_data(
+ mu_id, currentPage=1, panel="members", sortBy="dailyOrdersCompleted", weekFilter=f"week{weeks_ago}", search=name
+ ).json()
+ return member.get("panelContents", {}).get("members", [{}])[0].get("dailyOrdersCompleted")
return 0
def get_possibly_empty_medals(self):
self.update_war_info()
for battle in self.all_battles.values():
for division in battle.div.values():
- if division.wall['dom'] == 50 or division.wall['dom'] > 98:
- yield division, division.wall['for'] == battle.invader.country.id
+ if division.wall["dom"] == 50 or division.wall["dom"] > 98:
+ yield division, division.wall["for"] == battle.invader.country.id
- def report_fighting(self, battle: classes.Battle, invader: bool, division: classes.BattleDivision, damage: float,
- hits: int):
+ def report_fighting(self, battle: classes.Battle, invader: bool, division: classes.BattleDivision, damage: float, hits: int):
self.reporter.report_fighting(battle, invader, division, damage, hits)
if self.config.telegram:
self.telegram.report_fight(battle, invader, division, damage, hits)
@@ -2323,11 +2399,11 @@ class CitizenMilitary(CitizenTravel):
# if ret.get('recoverableEnergyBuyFood'):
# self.buy_food()
# return self.get_deploy_inventory(division, side)
- if ret.get('captcha'):
+ if ret.get("captcha"):
self.do_captcha_challenge()
- if ret.get('error'):
- if ret.get('message') == 'Deployment disabled.':
- self._post_main_profile_update('options', params='{"optionName":"enable_web_deploy","optionValue":"on"}')
+ if ret.get("error"):
+ if ret.get("message") == "Deployment disabled.":
+ self._post_main_profile_update("options", params='{"optionName":"enable_web_deploy","optionValue":"on"}')
return self.get_deploy_inventory(division, side)
else:
self.report_error(f"Unable to get deployment inventory because: {ret.get('message')}")
@@ -2336,21 +2412,21 @@ class CitizenMilitary(CitizenTravel):
def deploy(self, division: classes.BattleDivision, side: classes.BattleSide, energy: int, _retry=0) -> int:
_energy = int(energy)
deploy_inv = self.get_deploy_inventory(division, side)
- if not deploy_inv['minEnergy'] <= energy <= deploy_inv['maxEnergy']:
+ if not deploy_inv["minEnergy"] <= energy <= deploy_inv["maxEnergy"]:
return 0
energy_sources = {}
source_idx = 0
- recoverable = deploy_inv['recoverableEnergy']
- for source in reversed(sorted(deploy_inv['energySources'], key=lambda s: (s['type'], s.get('quality', 0)))):
- if source['type'] == 'pool':
- _energy -= source['energy']
- elif source['type'] in ['food', 'energy_bar']:
- recovers = source['energy'] // source['amount']
- amount = (recoverable if source['type'] == 'food' else _energy) // recovers
- amount = amount if amount < source['amount'] else source['amount']
+ recoverable = deploy_inv["recoverableEnergy"]
+ for source in reversed(sorted(deploy_inv["energySources"], key=lambda s: (s["type"], s.get("quality", 0)))):
+ if source["type"] == "pool":
+ _energy -= source["energy"]
+ elif source["type"] in ["food", "energy_bar"]:
+ recovers = source["energy"] // source["amount"]
+ amount = (recoverable if source["type"] == "food" else _energy) // recovers
+ amount = amount if amount < source["amount"] else source["amount"]
if amount > 0:
- energy_sources.update({f'energySources[{source_idx}][quality]': source['quality']})
- energy_sources.update({f'energySources[{source_idx}][amount]': amount})
+ energy_sources.update({f"energySources[{source_idx}][quality]": source["quality"]})
+ energy_sources.update({f"energySources[{source_idx}][amount]": amount})
source_idx += 1
used_energy = amount * recovers
recoverable -= used_energy
@@ -2362,22 +2438,20 @@ class CitizenMilitary(CitizenTravel):
weapon_q = -1
weapon_strength = 0
if not division.is_air:
- for weapon in sorted(deploy_inv['weapons'], key=lambda w: w['damageperHit']):
- if (weapon['damageperHit'] or 0) > weapon_strength and (weapon['amount'] or 0) > 50:
- weapon_q = weapon['quality']
- r = self._post_fight_deploy_start_deploy(
- division.battle.id, side.id, division.id, energy, weapon_q, **energy_sources
- ).json()
- if r.get('error'):
+ for weapon in sorted(deploy_inv["weapons"], key=lambda w: w["damageperHit"]):
+ if (weapon["damageperHit"] or 0) > weapon_strength and (weapon["amount"] or 0) > 50:
+ weapon_q = weapon["quality"]
+ r = self._post_fight_deploy_start_deploy(division.battle.id, side.id, division.id, energy, weapon_q, **energy_sources).json()
+ if r.get("error"):
self.report_error(f"Deploy failed: '{r.get('message')}'")
- if r.get('message') == 'Deployment disabled.':
- self._post_main_profile_update('options', params='{"optionName":"enable_web_deploy","optionValue":"on"}')
+ if r.get("message") == "Deployment disabled.":
+ self._post_main_profile_update("options", params='{"optionName":"enable_web_deploy","optionValue":"on"}')
if _retry < 5:
- return self.deploy(division, side, energy, _retry+1)
+ return self.deploy(division, side, energy, _retry + 1)
else:
- self.report_error('Unable to deploy 5 times!')
+ self.report_error("Unable to deploy 5 times!")
return 0
- return r.get('deploymentId')
+ return r.get("deploymentId")
class CitizenPolitics(BaseCitizen):
@@ -2390,31 +2464,29 @@ class CitizenPolitics(BaseCitizen):
def candidate_for_party_presidency(self) -> Optional[Response]:
if self.politics.is_party_member:
- self._report_action('POLITIC_PARTY_PRESIDENT', 'Applied for party president elections')
+ self._report_action("POLITIC_PARTY_PRESIDENT", "Applied for party president elections")
return self._get_candidate_party(self.politics.party_slug)
else:
- self._report_action('POLITIC_CONGRESS',
- 'Unable to apply for party president elections - not a party member')
+ self._report_action("POLITIC_CONGRESS", "Unable to apply for party president elections - not a party member")
return None
def candidate_for_congress(self, presentation: str = "") -> Optional[Response]:
if self.politics.is_party_member:
- self._report_action('POLITIC_CONGRESS', 'Applied for congress elections')
+ self._report_action("POLITIC_CONGRESS", "Applied for congress elections")
return self._post_candidate_for_congress(presentation)
else:
- self._report_action('POLITIC_CONGRESS', 'Unable to apply for congress elections - not a party member')
+ self._report_action("POLITIC_CONGRESS", "Unable to apply for congress elections - not a party member")
return None
- def get_country_president_election_result(
- self, country: constants.Country, year: int, month: int
- ) -> Dict[str, int]:
+ def get_country_president_election_result(self, country: constants.Country, year: int, month: int) -> Dict[str, int]:
timestamp = int(constants.erep_tz.localize(datetime(year, month, 5)).timestamp())
resp = self._get_presidential_elections(country.id, timestamp)
candidates = re.findall(r'class="candidate_info">(.*?)', resp.text, re.S | re.M)
ret = {}
for candidate in candidates:
- name = re.search(r'', candidate)
+ name = re.search(
+ r'', candidate
+ )
name = name.group(1)
votes = re.search(r'(\d+) votes', candidate).group(1)
ret.update({name: int(votes)})
@@ -2424,58 +2496,56 @@ class CitizenPolitics(BaseCitizen):
class CitizenSocial(BaseCitizen):
def send_mail(self, subject: str, msg: str, ids: List[int]):
for player_id in ids:
- self._report_action('SOCIAL_MESSAGE', f'Sent a message to {player_id}',
- kwargs=dict(subject=subject, msg=msg, id=player_id))
+ self._report_action("SOCIAL_MESSAGE", f"Sent a message to {player_id}", kwargs=dict(subject=subject, msg=msg, id=player_id))
self._post_main_messages_compose(subject, msg, [player_id])
def write_on_country_wall(self, message: str) -> bool:
self._get_main()
- post_to_wall_as = re.findall(r'id="post_to_country_as".*?.*',
- self.r.text, re.S | re.M)
+ post_to_wall_as = re.findall(r'id="post_to_country_as".*?.*', self.r.text, re.S | re.M)
r = self._post_main_country_post_create(message, max(post_to_wall_as, key=int) if post_to_wall_as else 0)
- self._report_action('SOCIAL_WRITE_WALL_COUNTRY', 'Wrote a message to the country wall')
+ self._report_action("SOCIAL_WRITE_WALL_COUNTRY", "Wrote a message to the country wall")
return r.json()
def add_friend(self, player_id: int) -> Response:
resp = self._get_main_citizen_hovercard(player_id)
r_json = resp.json()
- if not any([r_json['isBanned'], r_json['isDead'], r_json['isFriend'], r_json['isOrg'], r_json['isSelf']]):
+ if not any([r_json["isBanned"], r_json["isDead"], r_json["isFriend"], r_json["isOrg"], r_json["isSelf"]]):
r = self._post_main_citizen_add_remove_friend(int(player_id), True)
self.write_log(f"{r_json['name']:<64} (id:{player_id:>11}) added as friend")
- self._report_action('SOCIAL_ADD_FRIEND', f"{r_json['name']:<64} (id:{player_id:>11}) added as friend")
+ self._report_action("SOCIAL_ADD_FRIEND", f"{r_json['name']:<64} (id:{player_id:>11}) added as friend")
return r
return resp
def add_every_player_as_friend(self):
cities = []
cities_dict = {}
- self.write_warning('This will take a lot of time.')
- rj = self._post_main_travel_data(regionId=662, check='getCountryRegions').json()
- for region_data in rj.get('regions', {}).values():
- cities.append(region_data['cityId'])
- cities_dict.update({region_data['cityId']: region_data['cityName']})
+ self.write_warning("This will take a lot of time.")
+ rj = self._post_main_travel_data(regionId=662, check="getCountryRegions").json()
+ for region_data in rj.get("regions", {}).values():
+ cities.append(region_data["cityId"])
+ cities_dict.update({region_data["cityId"]: region_data["cityName"]})
cities.sort(key=int)
for city_id in cities:
self.write_log(f"Adding friends from {cities_dict[city_id]} (id: {city_id})")
resp = self._get_main_city_data_residents(city_id).json()
- for resident in resp['widgets']['residents']['residents']:
- self.add_friend(resident['citizenId'])
- for page in range(2, resp['widgets']['residents']['numResults'] // 10 + 2):
+ for resident in resp["widgets"]["residents"]["residents"]:
+ self.add_friend(resident["citizenId"])
+ for page in range(2, resp["widgets"]["residents"]["numResults"] // 10 + 2):
r = self._get_main_city_data_residents(city_id, page)
resp = r.json()
- for resident in resp['widgets']['residents']['residents']:
- self.add_friend(resident['citizenId'])
+ for resident in resp["widgets"]["residents"]["residents"]:
+ self.add_friend(resident["citizenId"])
def get_community_notifications(self, page: int = 1) -> List[Dict[str, Any]]:
- return self._get_main_notifications_ajax_community(page).json().get('alertsList', [])
+ return self._get_main_notifications_ajax_community(page).json().get("alertsList", [])
def get_system_notifications(self, page: int = 1) -> List[Dict[str, Any]]:
- return self._get_main_notifications_ajax_system(page).json().get('alertsList', [])
+ return self._get_main_notifications_ajax_system(page).json().get("alertsList", [])
def get_report_notifications(self, page: int = 1) -> List[Dict[str, Any]]:
- return self._get_main_notifications_ajax_report(page).json().get('alertsList', [])
+ return self._get_main_notifications_ajax_report(page).json().get("alertsList", [])
def delete_community_notification(self, *notification_ids: int):
ids = []
@@ -2496,19 +2566,21 @@ class CitizenSocial(BaseCitizen):
self._post_main_notifications_ajax_report(ids)
def get_all_notifications(self, page: int = 1) -> Dict[str, List[Dict[str, Any]]]:
- return dict(community=self.get_community_notifications(),
- system=self.get_system_notifications(page),
- report=self.get_report_notifications(page))
+ return dict(
+ community=self.get_community_notifications(),
+ system=self.get_system_notifications(page),
+ report=self.get_report_notifications(page),
+ )
def delete_all_notifications(self):
for kind, notifications in self.get_all_notifications():
if notifications:
- if kind == 'community':
- self.delete_community_notification(*[n['id'] for n in notifications])
- elif kind == 'report':
- self.delete_report_notification(*[n['id'] for n in notifications])
- elif kind == 'system':
- self.delete_system_notification(*[n['id'] for n in notifications])
+ if kind == "community":
+ self.delete_community_notification(*[n["id"] for n in notifications])
+ elif kind == "report":
+ self.delete_report_notification(*[n["id"] for n in notifications])
+ elif kind == "system":
+ self.delete_system_notification(*[n["id"] for n in notifications])
else:
self.report_error(f'Unsupported notification kind: "{kind}"!')
@@ -2521,10 +2593,10 @@ class CitizenSocial(BaseCitizen):
if citizen_id is None:
citizen_id = self.details.citizen_id
profile = self.get_citizen_profile(citizen_id)
- name = profile.get('citizen', {}).get('name', '')
- city_id = profile.get('citizen', {}).get('residenceCityId')
+ name = profile.get("citizen", {}).get("name", "")
+ city_id = profile.get("citizen", {}).get("residenceCityId")
if city_id:
- return self._get_main_city_data_residents(city_id, params={'search': name}).json()
+ return self._get_main_city_data_residents(city_id, params={"search": name}).json()
class CitizenTasks(CitizenEconomy):
@@ -2540,19 +2612,19 @@ class CitizenTasks(CitizenEconomy):
def work(self):
if self.energy.food_fights >= 1:
- response = self._post_economy_work('work')
+ response = self._post_economy_work("work")
js = response.json()
- good_msg = ['already_worked', 'captcha']
- if not js.get('status') and not js.get('message') in good_msg:
- if js.get('message') in ['employee', 'money']:
+ good_msg = ["already_worked", "captcha"]
+ if not js.get("status") and not js.get("message") in good_msg:
+ if js.get("message") in ["employee", "money"]:
self.resign_from_employer()
self.find_new_job()
- elif js.get('message') in ['not_enough_health_food']:
+ elif js.get("message") in ["not_enough_health_food"]:
self.buy_food(120)
self.update_citizen_info()
self.work()
else:
- self.reporter.report_action('WORK', json_val=js)
+ self.reporter.report_action("WORK", json_val=js)
else:
if self.energy.food_fights < 1:
seconds = (self.energy.reference_time - self.now).total_seconds()
@@ -2563,23 +2635,23 @@ class CitizenTasks(CitizenEconomy):
def train(self):
r = self._get_main_training_grounds_json()
tg_json = r.json()
- self.details.gold = tg_json['page_details']['gold']
- self.tg_contract.update(free_train=tg_json['hasFreeTrain'])
- if tg_json['contracts']:
- self.tg_contract.update(**tg_json['contracts'][0])
+ self.details.gold = tg_json["page_details"]["gold"]
+ self.tg_contract.update(free_train=tg_json["hasFreeTrain"])
+ if tg_json["contracts"]:
+ self.tg_contract.update(**tg_json["contracts"][0])
tgs = []
- for data in sorted(tg_json['grounds'], key=lambda k: k['cost']):
- if data['default'] and not data['trained']:
- tgs.append(data['id'])
+ for data in sorted(tg_json["grounds"], key=lambda k: k["cost"]):
+ if data["default"] and not data["trained"]:
+ tgs.append(data["id"])
if tgs:
if self.energy.food_fights >= len(tgs):
response = self._post_economy_train(tgs)
- if not response.json().get('status'):
+ if not response.json().get("status"):
self.update_citizen_info()
self.train()
else:
- self.reporter.report_action('TRAIN', response.json())
+ self.reporter.report_action("TRAIN", response.json())
else:
if self.energy.food_fights < len(tgs):
large = max(self.energy.reference_time, self.now)
@@ -2593,15 +2665,15 @@ class CitizenTasks(CitizenEconomy):
self.update_job_info()
if self.ot_points >= 24 and self.energy.food_fights > 1:
r = self._post_economy_work_overtime()
- if not r.json().get('status') and r.json().get('message') == 'money':
+ if not r.json().get("status") and r.json().get("message") == "money":
self.resign_from_employer()
self.find_new_job()
else:
- if r.json().get('message') == 'employee':
+ if r.json().get("message") == "employee":
self.find_new_job()
- elif r.json().get('message') == 'not_enough_health_food':
+ elif r.json().get("message") == "not_enough_health_food":
self.buy_food(120)
- self.reporter.report_action('WORK_OT', r.json())
+ self.reporter.report_action("WORK_OT", r.json())
elif self.energy.food_fights < 1 and self.ot_points >= 24:
if self.energy.food_fights < 1:
large = max(self.energy.reference_time, self.now)
@@ -2612,51 +2684,52 @@ class CitizenTasks(CitizenEconomy):
def resign_from_employer(self) -> bool:
r = self._get_main_job_data()
- if r.json().get('isEmployee'):
- self._report_action('ECONOMY_RESIGN', 'Resigned from employer!', kwargs=r.json())
+ if r.json().get("isEmployee"):
+ self._report_action("ECONOMY_RESIGN", "Resigned from employer!", kwargs=r.json())
self._post_economy_resign()
return True
return False
def buy_tg_contract(self) -> Response:
- ret = self._post_main_buy_gold_items('gold', 'TrainingContract2', 1)
+ ret = self._post_main_buy_gold_items("gold", "TrainingContract2", 1)
try:
extra = ret.json()
except: # noqa
extra = {}
- self._report_action('ECONOMY_TG_CONTRACT', 'Bought TG Contract', kwargs=extra)
+ self._report_action("ECONOMY_TG_CONTRACT", "Bought TG Contract", kwargs=extra)
return ret
def find_new_job(self) -> bool:
r = self._get_economy_job_market_json(self.details.current_country.id)
- jobs = r.json().get('jobs')
+ jobs = r.json().get("jobs")
data = dict(citizen_id=0, salary=10)
for posting in jobs:
- salary = posting.get('salary')
- limit = posting.get('salaryLimit', 0)
- citizen_id = posting.get('citizen').get('id')
+ salary = posting.get("salary")
+ limit = posting.get("salaryLimit", 0)
+ citizen_id = posting.get("citizen").get("id")
- if (not limit or salary * 3 < limit) and salary > data['salary']:
+ if (not limit or salary * 3 < limit) and salary > data["salary"]:
data.update(citizen_id=citizen_id, salary=salary)
- return self.apply_to_employer(data['citizen_id'], data['salary'])
+ return self.apply_to_employer(data["citizen_id"], data["salary"])
def apply_to_employer(self, employer_id: int, salary: float) -> bool:
data = dict(citizenId=employer_id, salary=salary)
- self._report_action('ECONOMY_APPLY_FOR_JOB', f"I'm working now for #{employer_id}", kwargs=data)
+ self._report_action("ECONOMY_APPLY_FOR_JOB", f"I'm working now for #{employer_id}", kwargs=data)
r = self._post_economy_job_market_apply(employer_id, salary)
- return bool(r.json().get('status'))
+ return bool(r.json().get("status"))
def update_job_info(self):
resp = self._get_main_job_data()
- ot = resp.json().get('overTime', {})
+ ot = resp.json().get("overTime", {})
if ot:
- self.next_ot_time = utils.localize_timestamp(int(ot.get('nextOverTime', 0)))
- self.ot_points = ot.get('points', 0)
+ self.next_ot_time = utils.localize_timestamp(int(ot.get("nextOverTime", 0)))
+ self.ot_points = ot.get("points", 0)
-class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
- CitizenMedia, CitizenPolitics, CitizenSocial, CitizenMilitary, CitizenTasks):
+class _Citizen(
+ CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard, CitizenMedia, CitizenPolitics, CitizenSocial, CitizenMilitary, CitizenTasks
+):
def __init__(self, email: str = "", password: str = "", auto_login: bool = False):
super().__init__(email, password)
self._last_full_update = constants.min_datetime
@@ -2685,9 +2758,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
self.update_citizen_info()
self.reporter.do_init()
if self.config.telegram and self.config.telegram_chat_id:
- self.telegram.do_init(self.config.telegram_chat_id,
- self.config.telegram_token,
- self.name)
+ self.telegram.do_init(self.config.telegram_chat_id, self.config.telegram_token, self.name)
self.telegram.send_message(f"*Started* {utils.now():%F %T}")
self.init_logger()
@@ -2703,58 +2774,64 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
return
super().update_citizen_info(html)
- if self.promos.get('trainingContract'):
+ if self.promos.get("trainingContract"):
if not self.tg_contract:
self.train()
- if not self.tg_contract['free_train'] and self.tg_contract.get('active', False):
+ if not self.tg_contract["free_train"] and self.tg_contract.get("active", False):
if self.details.gold >= 54:
self.buy_tg_contract()
else:
- self.write_warning('Training ground contract active but '
- f"don't have enough gold ({self.details.gold}g {self.details.cc}cc)")
+ self.write_warning(
+ "Training ground contract active but " f"don't have enough gold ({self.details.gold}g {self.details.cc}cc)"
+ )
if self.energy.is_energy_full and self.config.telegram:
self.telegram.report_full_energy(self.energy.energy, self.energy.limit, self.energy.interval)
def check_for_notification_medals(self):
notifications = self._get_main_citizen_daily_assistant().json()
data: Dict[Tuple[str, Union[float, str]], Dict[str, Union[int, str, float]]] = {}
- for medal in notifications.get('notifications', []):
- if medal.get('details', {}).get('type') == 'citizenAchievement':
- params: dict = medal.get('details', {}).get('achievement')
- about: str = medal.get('body')
- title: str = medal.get('title')
- count: int = medal.get('details', {}).get('achievementAmount', 1)
+ for medal in notifications.get("notifications", []):
+ if medal.get("details", {}).get("type") == "citizenAchievement":
+ params: dict = medal.get("details", {}).get("achievement")
+ about: str = medal.get("body")
+ title: str = medal.get("title")
+ count: int = medal.get("details", {}).get("achievementAmount", 1)
- award_id: int = medal.get('id')
- if award_id and title and medal.get('details').get('isWallMaterial'):
+ award_id: int = medal.get("id")
+ if award_id and title and medal.get("details").get("isWallMaterial"):
self._post_main_wall_post_automatic(title.lower(), award_id)
- if params.get('ccValue'):
- reward = params.get('ccValue')
- currency = 'Currency'
- elif params.get('goldValue'):
- reward = params.get('goldValue')
- currency = 'Gold'
+ if params.get("ccValue"):
+ reward = params.get("ccValue")
+ currency = "Currency"
+ elif params.get("goldValue"):
+ reward = params.get("goldValue")
+ currency = "Gold"
else:
- reward = params.get('energyValue')
- currency = 'Energy'
+ reward = params.get("energyValue")
+ currency = "Energy"
if (title, reward) not in data:
- data[(title, reward)] = {'about': about, 'kind': title, 'reward': reward, 'count': count,
- 'currency': currency, 'params': medal.get('details', {})}
+ data[(title, reward)] = {
+ "about": about,
+ "kind": title,
+ "reward": reward,
+ "count": count,
+ "currency": currency,
+ "params": medal.get("details", {}),
+ }
else:
- data[(title, reward)]['count'] += count
- self._post_main_global_alerts_close(medal.get('id'))
+ data[(title, reward)]["count"] += count
+ self._post_main_global_alerts_close(medal.get("id"))
if data:
- msgs = [f"{d['count']} x {d['kind']}, totaling {d['count'] * d['reward']} "
- f"{d['currency']}" for d in data.values()]
+ msgs = [f"{d['count']} x {d['kind']}, totaling {d['count'] * d['reward']} " f"{d['currency']}" for d in data.values()]
msgs = "\n".join(msgs)
if self.config.telegram:
self.telegram.report_medal(msgs, len(data) > 1)
self.write_log(f"Found awards:\n{msgs}")
for info in data.values():
- self.reporter.report_action('NEW_MEDAL', info)
+ self.reporter.report_action("NEW_MEDAL", info)
def set_pin(self, pin: str):
self.details.pin = str(pin[:4])
@@ -2774,19 +2851,18 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
def update_weekly_challenge(self):
data = self._get_main_weekly_challenge_data().json()
- self.details.pp = data.get('player', {}).get('prestigePoints', 0)
+ self.details.pp = data.get("player", {}).get("prestigePoints", 0)
self.details.next_pp.clear()
- max_collectable_id = data.get('maxRewardId')
+ max_collectable_id = data.get("maxRewardId")
should_collect = False
- for reward in data.get('rewards', {}).get('normal', {}):
- status = reward.get('status', "")
- if status == 'rewarded':
+ for reward in data.get("rewards", {}).get("normal", {}):
+ status = reward.get("status", "")
+ if status == "rewarded":
continue
- elif status == 'completed':
+ elif status == "completed":
should_collect = True
- elif reward.get('icon', "") == 'energy_booster':
- pps = re.search(r"Reach (\d+) Prestige Points to unlock the following reward: \+1 Energy",
- reward.get('tooltip', ""))
+ elif reward.get("icon", "") == "energy_booster":
+ pps = re.search(r"Reach (\d+) Prestige Points to unlock the following reward: \+1 Energy", reward.get("tooltip", ""))
if pps:
self.details.next_pp.append(int(pps.group(1)))
if should_collect:
@@ -2797,9 +2873,11 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
if count > 0 and not force_fight:
if self.energy.food_fights - self.my_companies.ff_lockdown < count:
- log_msg = (f"Fight count modified (old count: {count} | FF: {self.energy.food_fights} | "
- f"WAM ff_lockdown: {self.my_companies.ff_lockdown} |"
- f" New count: {count - self.my_companies.ff_lockdown})")
+ log_msg = (
+ f"Fight count modified (old count: {count} | FF: {self.energy.food_fights} | "
+ f"WAM ff_lockdown: {self.my_companies.ff_lockdown} |"
+ f" New count: {count - self.my_companies.ff_lockdown})"
+ )
count -= self.my_companies.ff_lockdown
if count <= 0:
count = 0
@@ -2807,8 +2885,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
if self.max_time_till_full_ff > self.time_till_week_change:
max_count = (int(self.time_till_week_change.total_seconds()) // 360 * self.energy.interval) // 10
- log_msg = ('End for Weekly challenge is near '
- f"(Recoverable until WC end {max_count}hp | want to do {count}hits)")
+ log_msg = "End for Weekly challenge is near " f"(Recoverable until WC end {max_count}hp | want to do {count}hits)"
count = count if max_count > count else max_count
if not silent:
@@ -2844,83 +2921,86 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
sleep_seconds = (start_time - self.now).total_seconds()
self.stop_threads.wait(sleep_seconds if sleep_seconds > 0 else 0)
except: # noqa
- self.report_error('State updater crashed')
+ self.report_error("State updater crashed")
def send_state_update(self):
- data = dict(xp=self.details.xp, cc=self.details.cc, gold=self.details.gold, pp=self.details.pp,
- inv_total=self.inventory.total, inv=self.inventory.used,
- hp_limit=self.energy.limit,
- hp_interval=self.energy.interval, hp_available=self.energy.energy, food=self.food['total'], )
+ data = dict(
+ xp=self.details.xp,
+ cc=self.details.cc,
+ gold=self.details.gold,
+ pp=self.details.pp,
+ inv_total=self.inventory.total,
+ inv=self.inventory.used,
+ hp_limit=self.energy.limit,
+ hp_interval=self.energy.interval,
+ hp_available=self.energy.energy,
+ food=self.food["total"],
+ )
self.reporter.send_state_update(**data)
def send_inventory_update(self):
- self.reporter.report_action('INVENTORY', json_val=self.inventory.as_dict)
+ self.reporter.report_action("INVENTORY", json_val=self.inventory.as_dict)
def send_my_companies_update(self):
- self.reporter.report_action('COMPANIES', json_val=self.my_companies.as_dict)
+ self.reporter.report_action("COMPANIES", json_val=self.my_companies.as_dict)
def sell_produced_product(self, kind: str, quality: int = 1, amount: int = 0):
if not amount:
inv_resp = self._get_economy_inventory_items().json()
- category = 'rawMaterials' if kind.endswith('Raw') else 'finalProducts'
+ category = "rawMaterials" if kind.endswith("Raw") else "finalProducts"
item = f"{constants.INDUSTRIES[kind]}_{quality}"
- amount = inv_resp.get('inventoryItems').get(category).get('items').get(item).get('amount', 0)
+ amount = inv_resp.get("inventoryItems").get(category).get("items").get(item).get("amount", 0)
if amount >= 1:
- lowest_price = self.get_market_offers(kind, int(quality), self.details.citizenship)[f'q{int(quality)}']
+ lowest_price = self.get_market_offers(kind, int(quality), self.details.citizenship)[f"q{int(quality)}"]
if lowest_price.citizen_id == self.details.citizen_id:
price = lowest_price.price
else:
price = lowest_price.price - 0.01
- self.post_market_offer(industry=constants.INDUSTRIES[kind], amount=int(amount),
- quality=int(quality), price=price)
+ self.post_market_offer(industry=constants.INDUSTRIES[kind], amount=int(amount), quality=int(quality), price=price)
def _wam(self, holding: classes.Holding) -> NoReturn:
response = self.work_as_manager_in_holding(holding)
if response is None:
return
- if response.get('status'):
- self._report_action('WORK_AS_MANAGER', 'Worked as manager', kwargs=response)
+ if response.get("status"):
+ self._report_action("WORK_AS_MANAGER", "Worked as manager", kwargs=response)
if self.config.auto_sell:
- for kind, data in response.get('result', {}).get('production', {}).items():
+ for kind, data in response.get("result", {}).get("production", {}).items():
if data and kind in self.config.auto_sell:
- if kind in ['food', 'weapon', 'house', 'airplane']:
+ if kind in ["food", "weapon", "house", "airplane"]:
for quality, amount in data.items():
self.sell_produced_product(kind, quality)
- elif kind.endswith('Raw'):
+ elif kind.endswith("Raw"):
self.sell_produced_product(kind, 1)
else:
raise classes.ErepublikException(f"Unknown kind produced '{kind}'")
- elif self.config.auto_buy_raw and re.search(r"not_enough_[^_]*_raw", response.get('message')):
- raw_kind = re.search(r"not_enough_(\w+)_raw", response.get('message'))
+ elif self.config.auto_buy_raw and re.search(r"not_enough_[^_]*_raw", response.get("message")):
+ raw_kind = re.search(r"not_enough_(\w+)_raw", response.get("message"))
if raw_kind:
raw_kind = raw_kind.group(1)
- result = response.get('result', {})
- amount_needed = round(result.get('consume', 0) - result.get('stock', 0) + 0.5)
+ result = response.get("result", {})
+ amount_needed = round(result.get("consume", 0) - result.get("stock", 0) + 0.5)
self._report_action(
- 'WORK_AS_MANAGER', f"Unable to wam! Missing {amount_needed} {raw_kind}, will try to buy.",
- kwargs=response
+ "WORK_AS_MANAGER", f"Unable to wam! Missing {amount_needed} {raw_kind}, will try to buy.", kwargs=response
)
start_place = (self.details.current_country, self.details.current_region)
while amount_needed > 0:
amount = amount_needed
- best_offer = self.get_market_offers(f"{raw_kind}Raw")['q1']
+ best_offer = self.get_market_offers(f"{raw_kind}Raw")["q1"]
amount = best_offer.amount if amount >= best_offer.amount else amount
if not best_offer.country == self.details.current_country:
self.travel_to_country(best_offer.country)
- self._report_action('ECONOMY_BUY',
- f"Attempting to buy {amount} {raw_kind} for {best_offer.price * amount}cc")
+ self._report_action("ECONOMY_BUY", f"Attempting to buy {amount} {raw_kind} for {best_offer.price * amount}cc")
rj = self.buy_from_market(amount=amount, offer=best_offer.offer_id)
- if not rj.get('error'):
+ if not rj.get("error"):
amount_needed -= amount
else:
- self.write_warning(rj.get('message', ""))
- self._report_action(
- 'ECONOMY_BUY', f"Unable to buy products! Reason: {rj.get('message')}", kwargs=rj
- )
+ self.write_warning(rj.get("message", ""))
+ self._report_action("ECONOMY_BUY", f"Unable to buy products! Reason: {rj.get('message')}", kwargs=rj)
break
else:
if not start_place == (self.details.current_country, self.details.current_region):
@@ -2931,25 +3011,25 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
if not start_place == (self.details.current_country, self.details.current_region):
self.travel_to_residence()
return
- elif response.get('message') == 'not_enough_health_food':
+ elif response.get("message") == "not_enough_health_food":
self.buy_food()
self._wam(holding)
- elif response.get('message') == 'tax_money':
- self._report_action('WORK_AS_MANAGER', 'Not enough money to work as manager!', kwargs=response)
- self.write_warning('Not enough money to work as manager!')
+ elif response.get("message") == "tax_money":
+ self._report_action("WORK_AS_MANAGER", "Not enough money to work as manager!", kwargs=response)
+ self.write_warning("Not enough money to work as manager!")
else:
- msg = f'I was not able to wam and or employ because:\n{response}'
- self._report_action('WORK_AS_MANAGER', f'Worked as manager failed: {msg}', kwargs=response)
+ msg = f"I was not able to wam and or employ because:\n{response}"
+ self._report_action("WORK_AS_MANAGER", f"Worked as manager failed: {msg}", kwargs=response)
self.write_warning(msg)
def work_as_manager(self) -> bool:
- """ Does Work as Manager in all holdings with wam. If employees assigned - work them also
+ """Does Work as Manager in all holdings with wam. If employees assigned - work them also
:return: if has more wam work to do
:rtype: bool
"""
if self.restricted_ip:
- self._report_action('IP_BLACKLISTED', 'Work as manager is not allowed from restricted IP!')
+ self._report_action("IP_BLACKLISTED", "Work as manager is not allowed from restricted IP!")
return False
self.update_citizen_info()
self.update_companies()
@@ -2968,8 +3048,8 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
for holding in regions.values():
raw_usage = holding.get_wam_raw_usage()
free_storage = self.inventory.total - self.inventory.used
- if (raw_usage['frm'] + raw_usage['wrm']) * 100 > free_storage:
- self._report_action('WAM_UNAVAILABLE', 'Not enough storage!')
+ if (raw_usage["frm"] + raw_usage["wrm"]) * 100 > free_storage:
+ self._report_action("WAM_UNAVAILABLE", "Not enough storage!")
continue
self.travel_to_holding(holding)
self._wam(holding)
@@ -2982,7 +3062,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
self.travel_to_residence()
return bool(wam_count)
else:
- self.write_warning('Did not WAM because I would mess up levelup!')
+ self.write_warning("Did not WAM because I would mess up levelup!")
self.my_companies.ff_lockdown = 0
self.update_companies()
@@ -3005,7 +3085,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
continue
self.stop_threads.wait(90)
except: # noqa
- self.report_error('Command central is broken')
+ self.report_error("Command central is broken")
class Citizen(_Citizen):
@@ -3023,7 +3103,7 @@ class Citizen(_Citizen):
def update_weekly_challenge(self):
if not self._update_lock.wait(self._update_timeout):
- e = f'Update concurrency not freed in {self._update_timeout}sec!'
+ e = f"Update concurrency not freed in {self._update_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3034,7 +3114,7 @@ class Citizen(_Citizen):
def update_companies(self):
if not self._update_lock.wait(self._update_timeout):
- e = f'Update concurrency not freed in {self._update_timeout}sec!'
+ e = f"Update concurrency not freed in {self._update_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3045,7 +3125,7 @@ class Citizen(_Citizen):
def update_war_info(self):
if not self._update_lock.wait(self._update_timeout):
- e = f'Update concurrency not freed in {self._update_timeout}sec!'
+ e = f"Update concurrency not freed in {self._update_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3056,7 +3136,7 @@ class Citizen(_Citizen):
def update_job_info(self):
if not self._update_lock.wait(self._update_timeout):
- e = f'Update concurrency not freed in {self._update_timeout}sec!'
+ e = f"Update concurrency not freed in {self._update_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3067,7 +3147,7 @@ class Citizen(_Citizen):
def update_money(self, page: int = 0, currency: int = 62):
if not self._update_lock.wait(self._update_timeout):
- e = f'Update concurrency not freed in {self._update_timeout}sec!'
+ e = f"Update concurrency not freed in {self._update_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3078,7 +3158,7 @@ class Citizen(_Citizen):
def update_inventory(self):
if not self._update_lock.wait(self._update_timeout):
- e = f'Update concurrency not freed in {self._update_timeout}sec!'
+ e = f"Update concurrency not freed in {self._update_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3089,7 +3169,7 @@ class Citizen(_Citizen):
def _work_as_manager(self, wam_holding: classes.Holding) -> Optional[Dict[str, Any]]:
if not self._concurrency_lock.wait(self._concurrency_timeout):
- e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
+ e = f"Concurrency not freed in {self._concurrency_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3098,10 +3178,16 @@ class Citizen(_Citizen):
finally:
self._concurrency_lock.set()
- def fight(self, battle: classes.Battle, division: classes.BattleDivision, side: classes.BattleSide = None,
- count: int = None, use_ebs: bool = False) -> Optional[int]:
+ def fight(
+ self,
+ battle: classes.Battle,
+ division: classes.BattleDivision,
+ side: classes.BattleSide = None,
+ count: int = None,
+ use_ebs: bool = False,
+ ) -> Optional[int]:
if not self._concurrency_lock.wait(self._concurrency_timeout):
- e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
+ e = f"Concurrency not freed in {self._concurrency_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3110,10 +3196,11 @@ class Citizen(_Citizen):
finally:
self._concurrency_lock.set()
- def deploy_bomb(self, battle: classes.Battle, division: classes.BattleDivision, bomb_id: int, inv_side: bool,
- count: int = 1) -> Optional[int]:
+ def deploy_bomb(
+ self, battle: classes.Battle, division: classes.BattleDivision, bomb_id: int, inv_side: bool, count: int = 1
+ ) -> Optional[int]:
if not self._concurrency_lock.wait(self._concurrency_timeout):
- e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
+ e = f"Concurrency not freed in {self._concurrency_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3124,7 +3211,7 @@ class Citizen(_Citizen):
def buy_market_offer(self, offer: classes.OfferItem, amount: int = None) -> Optional[Dict[str, Any]]:
if not self._concurrency_lock.wait(self._concurrency_timeout):
- e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
+ e = f"Concurrency not freed in {self._concurrency_timeout}sec!"
self.report_error(e)
return None
try:
@@ -3136,8 +3223,14 @@ class Citizen(_Citizen):
@property
def as_dict(self):
d = super().as_dict
- d.update(locks=dict(concurrency_lock=self._concurrency_lock.is_set(), update_lock=self._update_lock.is_set(),
- concurrency_timeout=self._concurrency_timeout, update_timeout=self._update_timeout))
+ d.update(
+ locks=dict(
+ concurrency_lock=self._concurrency_lock.is_set(),
+ update_lock=self._update_lock.is_set(),
+ concurrency_timeout=self._concurrency_timeout,
+ update_timeout=self._update_timeout,
+ )
+ )
return d
def set_locks(self):
diff --git a/erepublik/classes.py b/erepublik/classes.py
index 9236f3c..d747122 100644
--- a/erepublik/classes.py
+++ b/erepublik/classes.py
@@ -12,9 +12,25 @@ from requests import HTTPError, Response, Session, post
from erepublik import _types as types
from erepublik import constants, utils
-__all__ = ['Battle', 'BattleDivision', 'BattleSide', 'Company', 'Config', 'Details', 'Energy', 'ErepublikException',
- 'ErepublikNetworkException', 'EnergyToFight', 'Holding', 'Inventory', 'MyCompanies', 'OfferItem', 'Politics',
- 'Reporter', 'TelegramReporter', ]
+__all__ = [
+ "Battle",
+ "BattleDivision",
+ "BattleSide",
+ "Company",
+ "Config",
+ "Details",
+ "Energy",
+ "ErepublikException",
+ "ErepublikNetworkException",
+ "EnergyToFight",
+ "Holding",
+ "Inventory",
+ "MyCompanies",
+ "OfferItem",
+ "Politics",
+ "Reporter",
+ "TelegramReporter",
+]
class ErepublikException(Exception):
@@ -39,7 +55,7 @@ class CaptchaSessionError(ErepublikNetworkException):
class Holding:
id: int
region: int
- companies: List['Company']
+ companies: List["Company"]
name: str
_citizen = weakref.ReferenceType
@@ -47,16 +63,16 @@ class Holding:
self._citizen = weakref.ref(citizen)
self.id: int = _id
self.region: int = region
- self.companies: List['Company'] = list()
+ self.companies: List["Company"] = list()
if name:
self.name = name
else:
comp_sum = len(self.companies)
name = f"Holding (#{self.id}) with {comp_sum} "
if comp_sum == 1:
- name += 'company'
+ name += "company"
else:
- name += 'companies'
+ name += "companies"
self.name = name
@property
@@ -64,20 +80,20 @@ class Holding:
return len([1 for company in self.companies if company.wam_enabled and not company.already_worked])
@property
- def wam_companies(self) -> Iterable['Company']:
+ def wam_companies(self) -> Iterable["Company"]:
return [company for company in self.companies if company.wam_enabled]
@property
- def employable_companies(self) -> Iterable['Company']:
+ def employable_companies(self) -> Iterable["Company"]:
return [company for company in self.companies if company.preset_works]
- def add_company(self, company: 'Company') -> NoReturn:
+ def add_company(self, company: "Company") -> NoReturn:
self.companies.append(company)
self.companies.sort()
def get_wam_raw_usage(self) -> Dict[str, Decimal]:
- frm = Decimal('0.00')
- wrm = Decimal('0.00')
+ frm = Decimal("0.00")
+ wrm = Decimal("0.00")
for company in self.wam_companies:
if company.industry in [1, 7, 8, 9, 10, 11]:
frm += company.raw_usage
@@ -85,11 +101,11 @@ class Holding:
wrm += company.raw_usage
return dict(frm=frm, wrm=wrm)
- def get_wam_companies(self, raw_factory: bool = None) -> List['Company']:
+ def get_wam_companies(self, raw_factory: bool = None) -> List["Company"]:
raw = []
factory = []
for company in self.wam_companies:
- if not company.already_worked and not company.cannot_wam_reason == 'war':
+ if not company.already_worked and not company.cannot_wam_reason == "war":
if company.is_raw:
raw.append(company)
else:
@@ -103,9 +119,9 @@ class Holding:
comp = len(self.companies)
name = f"Holding (#{self.id}) with {comp} "
if comp == 1:
- name += 'company'
+ name += "company"
else:
- name += 'companies'
+ name += "companies"
return name
def __repr__(self):
@@ -113,8 +129,7 @@ class Holding:
@property
def as_dict(self) -> Dict[str, Union[str, int, List[Dict[str, Union[str, int, bool, float, Decimal]]]]]:
- return dict(name=self.name, id=self.id, region=self.region,
- companies=[c.as_dict for c in self.companies], wam_count=self.wam_count)
+ return dict(name=self.name, id=self.id, region=self.region, companies=[c.as_dict for c in self.companies], wam_count=self.wam_count)
@property
def citizen(self):
@@ -137,9 +152,20 @@ class Company:
preset_works: int
def __init__(
- self, holding: Holding, _id: int, quality: int, is_raw: bool, effective_bonus: Decimal, raw_usage: Decimal,
- base_production: Decimal, wam_enabled: bool, can_wam: bool, cannot_wam_reason: str, industry: int,
- already_worked: bool, preset_works: int
+ self,
+ holding: Holding,
+ _id: int,
+ quality: int,
+ is_raw: bool,
+ effective_bonus: Decimal,
+ raw_usage: Decimal,
+ base_production: Decimal,
+ wam_enabled: bool,
+ can_wam: bool,
+ cannot_wam_reason: str,
+ industry: int,
+ already_worked: bool,
+ preset_works: int,
):
self._holding = weakref.ref(holding)
self.id: int = _id
@@ -154,7 +180,7 @@ class Company:
self.products_made = self.raw_usage = Decimal(base_production) * Decimal(effective_bonus)
if not self.is_raw:
- self.raw_usage = - self.products_made * raw_usage
+ self.raw_usage = -self.products_made * raw_usage
def _get_real_quality(self, quality) -> int:
# 7: 'FRM q1', 8: 'FRM q2', 9: 'FRM q3', 10: 'FRM q4', 11: 'FRM q5',
@@ -196,22 +222,22 @@ class Company:
def __hash__(self):
return hash(self._sort_keys)
- def __lt__(self, other: 'Company'):
+ def __lt__(self, other: "Company"):
return self._sort_keys < other._sort_keys
- def __le__(self, other: 'Company'):
+ def __le__(self, other: "Company"):
return self._sort_keys <= other._sort_keys
- def __gt__(self, other: 'Company'):
+ def __gt__(self, other: "Company"):
return self._sort_keys > other._sort_keys
- def __ge__(self, other: 'Company'):
+ def __ge__(self, other: "Company"):
return self._sort_keys >= other._sort_keys
- def __eq__(self, other: 'Company'):
+ def __eq__(self, other: "Company"):
return self._sort_keys == other._sort_keys
- def __ne__(self, other: 'Company'):
+ def __ne__(self, other: "Company"):
return self._sort_keys != other._sort_keys
def __str__(self):
@@ -225,10 +251,21 @@ class Company:
@property
def as_dict(self) -> Dict[str, Union[str, int, bool, float, Decimal]]:
- return dict(name=str(self), holding=self.holding.id, id=self.id, quality=self.quality, is_raw=self.is_raw,
- raw_usage=self.raw_usage, products_made=self.products_made, wam_enabled=self.wam_enabled,
- can_wam=self.can_wam, cannot_wam_reason=self.cannot_wam_reason, industry=self.industry,
- already_worked=self.already_worked, preset_works=self.preset_works)
+ return dict(
+ name=str(self),
+ holding=self.holding.id,
+ id=self.id,
+ quality=self.quality,
+ is_raw=self.is_raw,
+ raw_usage=self.raw_usage,
+ products_made=self.products_made,
+ wam_enabled=self.wam_enabled,
+ can_wam=self.can_wam,
+ cannot_wam_reason=self.cannot_wam_reason,
+ industry=self.industry,
+ already_worked=self.already_worked,
+ preset_works=self.preset_works,
+ )
def dissolve(self) -> Response:
self.holding.citizen.write_log(f"{self} dissolved!")
@@ -265,12 +302,10 @@ class MyCompanies:
:param holdings: Parsed JSON to dict from en/economy/myCompanies
"""
for holding in holdings.values():
- if holding.get('id') not in self.holdings:
- self.holdings.update({
- int(holding.get('id')): Holding(holding['id'], holding['region_id'], self.citizen, holding['name'])
- })
+ if holding.get("id") not in self.holdings:
+ self.holdings.update({int(holding.get("id")): Holding(holding["id"], holding["region_id"], self.citizen, holding["name"])})
if not self.holdings.get(0):
- self.holdings.update({0: Holding(0, 0, self.citizen, 'Unassigned')}) # unassigned
+ self.holdings.update({0: Holding(0, 0, self.citizen, "Unassigned")}) # unassigned
def prepare_companies(self, companies: Dict[str, Dict[str, Any]]):
"""
@@ -278,19 +313,27 @@ class MyCompanies:
"""
self.__clear_data()
for company_dict in companies.values():
- holding = self.holdings.get(int(company_dict['holding_company_id']))
- quality = company_dict.get('quality')
- is_raw = company_dict.get('is_raw')
+ holding = self.holdings.get(int(company_dict["holding_company_id"]))
+ quality = company_dict.get("quality")
+ is_raw = company_dict.get("is_raw")
if is_raw:
- raw_usage = Decimal('0.0')
+ raw_usage = Decimal("0.0")
else:
- raw_usage = Decimal(str(company_dict.get('upgrades').get(str(quality)).get('raw_usage')))
+ raw_usage = Decimal(str(company_dict.get("upgrades").get(str(quality)).get("raw_usage")))
company = Company(
- holding, company_dict.get('id'), quality, is_raw,
- Decimal(str(company_dict.get('effective_bonus'))) / 100,
- raw_usage, Decimal(str(company_dict.get('base_production'))), company_dict.get('wam_enabled'),
- company_dict.get('can_work_as_manager'), company_dict.get('cannot_work_as_manager_reason'),
- company_dict.get('industry_id'), company_dict.get('already_worked'), company_dict.get('preset_works')
+ holding,
+ company_dict.get("id"),
+ quality,
+ is_raw,
+ Decimal(str(company_dict.get("effective_bonus"))) / 100,
+ raw_usage,
+ Decimal(str(company_dict.get("base_production"))),
+ company_dict.get("wam_enabled"),
+ company_dict.get("can_work_as_manager"),
+ company_dict.get("cannot_work_as_manager_reason"),
+ company_dict.get("industry_id"),
+ company_dict.get("already_worked"),
+ company_dict.get("preset_works"),
)
self._companies.add(company)
holding.add_company(company)
@@ -326,13 +369,20 @@ class MyCompanies:
self._companies.clear()
@property
- def as_dict(self) -> Dict[str, Union[str, int, datetime.datetime, Dict[str, Dict[str, Union[
- str, int, List[Dict[str, Union[str, int, bool, float, Decimal]]]]
- ]]]]:
- return dict(name=str(self), work_units=self.work_units, next_ot_time=self.next_ot_time,
- ff_lockdown=self.ff_lockdown,
- holdings={str(hi): h.as_dict for hi, h in self.holdings.items()},
- company_count=sum(1 for _ in self.companies))
+ def as_dict(
+ self,
+ ) -> Dict[
+ str,
+ Union[str, int, datetime.datetime, Dict[str, Dict[str, Union[str, int, List[Dict[str, Union[str, int, bool, float, Decimal]]]]]]],
+ ]:
+ return dict(
+ name=str(self),
+ work_units=self.work_units,
+ next_ot_time=self.next_ot_time,
+ ff_lockdown=self.ff_lockdown,
+ holdings={str(hi): h.as_dict for hi, h in self.holdings.items()},
+ company_count=sum(1 for _ in self.companies),
+ )
@property
def citizen(self):
@@ -408,16 +458,37 @@ class Config:
@property
def as_dict(self) -> Dict[str, Union[bool, int, str, List[str]]]:
- return dict(email=self.email, work=self.work, train=self.train, wam=self.wam, ot=self.ot,
- 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, travel_to_fight=self.travel_to_fight,
- always_travel=self.always_travel, epic_hunt=self.epic_hunt, epic_hunt_ebs=self.epic_hunt_ebs,
- rw_def_side=self.rw_def_side, interactive=self.interactive, maverick=self.maverick,
- 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,
- telegram=self.telegram, telegram_chat_id=self.telegram_chat_id, telegram_token=self.telegram_token,
- spin_wheel_of_fortune=self.spin_wheel_of_fortune)
+ return dict(
+ email=self.email,
+ work=self.work,
+ train=self.train,
+ wam=self.wam,
+ ot=self.ot,
+ 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,
+ travel_to_fight=self.travel_to_fight,
+ always_travel=self.always_travel,
+ epic_hunt=self.epic_hunt,
+ epic_hunt_ebs=self.epic_hunt_ebs,
+ rw_def_side=self.rw_def_side,
+ interactive=self.interactive,
+ maverick=self.maverick,
+ 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,
+ telegram=self.telegram,
+ telegram_chat_id=self.telegram_chat_id,
+ telegram_token=self.telegram_token,
+ spin_wheel_of_fortune=self.spin_wheel_of_fortune,
+ )
class Energy:
@@ -434,12 +505,12 @@ class Energy:
@property
def recovered(self):
- warnings.warn('Deprecated since auto auto-eat! Will be removed soon. Use Energy.energy', DeprecationWarning)
+ warnings.warn("Deprecated since auto auto-eat! Will be removed soon. Use Energy.energy", DeprecationWarning)
return self.energy
@property
def recoverable(self):
- warnings.warn('Deprecated since auto auto-eat! Will be removed soon. Use Energy.energy', DeprecationWarning)
+ warnings.warn("Deprecated since auto auto-eat! Will be removed soon. Use Energy.energy", DeprecationWarning)
return 0
def set_reference_time(self, recovery_time: datetime.datetime):
@@ -459,12 +530,12 @@ class Energy:
@property
def is_recoverable_full(self):
- warnings.warn('Deprecated since auto auto-eat! Will be removed soon. Use Energy.is_energy_full', DeprecationWarning)
+ warnings.warn("Deprecated since auto auto-eat! Will be removed soon. Use Energy.is_energy_full", DeprecationWarning)
return self.is_energy_full
@property
def is_recovered_full(self):
- warnings.warn('Deprecated since auto auto-eat! Will be removed soon. Use Energy.is_energy_full', DeprecationWarning)
+ warnings.warn("Deprecated since auto auto-eat! Will be removed soon. Use Energy.is_energy_full", DeprecationWarning)
return self.is_energy_full
@property
@@ -473,14 +544,19 @@ class Energy:
@property
def available(self):
- warnings.warn('Deprecated since auto auto-eat! Will be removed soon. Use Energy.energy', DeprecationWarning)
+ warnings.warn("Deprecated since auto auto-eat! Will be removed soon. Use Energy.energy", DeprecationWarning)
return self.energy
@property
def as_dict(self) -> Dict[str, Union[int, datetime.datetime, bool]]:
- return dict(limit=self.limit, interval=self.interval, energy=self.energy,
- reference_time=self.reference_time, food_fights=self.food_fights,
- is_energy_full=self.is_energy_full)
+ return dict(
+ limit=self.limit,
+ interval=self.interval,
+ energy=self.energy,
+ reference_time=self.reference_time,
+ food_fights=self.food_fights,
+ is_energy_full=self.is_energy_full,
+ )
class Details:
@@ -504,7 +580,7 @@ class Details:
def __init__(self):
self.next_pp = []
self.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}
- _default_country = constants.Country(0, 'Unknown', 'Unknown', 'XX')
+ _default_country = constants.Country(0, "Unknown", "Unknown", "XX")
self.citizenship = self.current_country = self.residence_country = _default_country
@property
@@ -535,12 +611,25 @@ class Details:
@property
def as_dict(self) -> Dict[str, Union[int, float, str, constants.Country, bool]]:
- return dict(xp=self.xp, cc=self.cc, pp=self.pp, pin=self.pin, gold=self.gold, next_pp=self.next_pp,
- level=self.level, citizen_id=self.citizen_id, citizenship=self.citizenship,
- current_region=self.current_region, current_country=self.current_country,
- residence_region=self.residence_region, residence_country=self.residence_country,
- daily_task_done=self.daily_task_done, daily_task_reward=self.daily_task_reward,
- mayhem_skills=self.mayhem_skills, xp_till_level_up=self.xp_till_level_up)
+ return dict(
+ xp=self.xp,
+ cc=self.cc,
+ pp=self.pp,
+ pin=self.pin,
+ gold=self.gold,
+ next_pp=self.next_pp,
+ level=self.level,
+ citizen_id=self.citizen_id,
+ citizenship=self.citizenship,
+ current_region=self.current_region,
+ current_country=self.current_country,
+ residence_region=self.residence_region,
+ residence_country=self.residence_country,
+ daily_task_done=self.daily_task_done,
+ daily_task_reward=self.daily_task_reward,
+ mayhem_skills=self.mayhem_skills,
+ xp_till_level_up=self.xp_till_level_up,
+ )
@property
def is_elite(self):
@@ -558,9 +647,14 @@ class Politics:
@property
def as_dict(self) -> Dict[str, Union[bool, int, str]]:
- return dict(is_party_member=self.is_party_member, party_id=self.party_id, party_slug=self.party_slug,
- is_party_president=self.is_party_president, is_congressman=self.is_congressman,
- is_country_president=self.is_country_president)
+ return dict(
+ is_party_member=self.is_party_member,
+ party_id=self.party_id,
+ party_slug=self.party_slug,
+ is_party_president=self.is_party_president,
+ is_congressman=self.is_congressman,
+ is_country_president=self.is_country_president,
+ )
class House:
@@ -596,17 +690,22 @@ class Reporter:
@property
def as_dict(self) -> Dict[str, Union[bool, int, str, List[Dict[Any, Any]]]]:
- return dict(name=self.name, email=self.email, citizen_id=self.citizen_id, key=self.key, allowed=self.allowed,
- queue=self.__to_update)
+ return dict(
+ name=self.name, email=self.email, citizen_id=self.citizen_id, key=self.key, allowed=self.allowed, queue=self.__to_update
+ )
def __init__(self, citizen):
self._citizen = weakref.ref(citizen)
self._req = Session()
self.url = "https://api.erep.lv"
- self._req.headers.update({"user-agent": 'eRepublik Script Reporter v3',
- 'erep-version': utils.__version__,
- 'erep-user-id': str(self.citizen_id),
- 'erep-user-name': self.citizen.name})
+ self._req.headers.update(
+ {
+ "user-agent": "eRepublik Script Reporter v3",
+ "erep-version": utils.__version__,
+ "erep-user-id": str(self.citizen_id),
+ "erep-user-name": self.citizen.name,
+ }
+ )
self.__to_update = []
self.__registered: bool = False
@@ -651,67 +750,102 @@ class Reporter:
if not self.__registered:
r = self.__bot_update(dict(key=self.key, check=True, player_id=self.citizen_id))
if r:
- if not r.json().get('status'):
- self._req.post(f"{self.url}/bot/register", json=dict(name=self.name, email=self.email,
- player_id=self.citizen_id))
+ if not r.json().get("status"):
+ self._req.post(f"{self.url}/bot/register", json=dict(name=self.name, email=self.email, player_id=self.citizen_id))
self.__registered = True
self.allowed = True
- self.report_action('STARTED', value=utils.now().strftime("%F %T"))
+ 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):
+ 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,
- ))
+ 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,
+ ),
+ )
self._bot_update(data)
def report_action(self, action: str, json_val: Dict[Any, Any] = None, value: str = None):
- json_data = dict(
- player_id=getattr(self, 'citizen_id', None), log={'action': action}, key=getattr(self, 'key', None)
- )
+ json_data = dict(player_id=getattr(self, "citizen_id", None), log={"action": action}, key=getattr(self, "key", None))
if json_val:
- json_data['log'].update(dict(json=json_val))
+ json_data["log"].update(dict(json=json_val))
if value:
- json_data['log'].update(dict(value=value))
+ json_data["log"].update(dict(value=value))
if not any([self.key, self.email, self.name, self.citizen_id]):
return
self._bot_update(json_data)
- def report_fighting(self, battle: 'Battle', invader: bool, division: 'BattleDivision', damage: float, hits: int):
+ def report_fighting(self, battle: "Battle", invader: bool, division: "BattleDivision", damage: float, hits: int):
side = battle.invader if invader else battle.defender
- self.report_action('FIGHT', dict(battle_id=battle.id, side=side, dmg=damage,
- air=battle.has_air, hits=hits,
- round=battle.zone_id, extra=dict(battle=battle, side=side, division=division)))
+ self.report_action(
+ "FIGHT",
+ dict(
+ battle_id=battle.id,
+ side=side,
+ dmg=damage,
+ air=battle.has_air,
+ hits=hits,
+ round=battle.zone_id,
+ extra=dict(battle=battle, side=side, division=division),
+ ),
+ )
def report_money_donation(self, citizen_id: int, amount: float, is_currency: bool = True):
- cur = 'cc' if is_currency else 'gold'
- self.report_action('DONATE_MONEY', dict(citizen_id=citizen_id, amount=amount, currency=cur),
- f"Successfully donated {amount}{cur} to citizen with id {citizen_id}!")
+ cur = "cc" if is_currency else "gold"
+ self.report_action(
+ "DONATE_MONEY",
+ dict(citizen_id=citizen_id, amount=amount, currency=cur),
+ f"Successfully donated {amount}{cur} to citizen with id {citizen_id}!",
+ )
def report_item_donation(self, citizen_id: int, amount: float, quality: int, industry: str):
- self.report_action('DONATE_ITEMS',
- dict(citizen_id=citizen_id, amount=amount, quality=quality, industry=industry),
- f"Successfully donated {amount} x {industry} q{quality} to citizen with id {citizen_id}!")
+ self.report_action(
+ "DONATE_ITEMS",
+ dict(citizen_id=citizen_id, amount=amount, quality=quality, industry=industry),
+ f"Successfully donated {amount} x {industry} q{quality} to citizen with id {citizen_id}!",
+ )
def report_promo(self, kind: str, time_until: datetime.datetime):
self._req.post(f"{self.url}/promos/add/", data=dict(kind=kind, time_untill=time_until))
- def fetch_battle_priorities(self, country: constants.Country) -> List['Battle']:
+ def fetch_battle_priorities(self, country: constants.Country) -> List["Battle"]:
try:
- battle_response = self._req.get(f'{self.url}/api/v1/battles/{country.id}')
- return [self.citizen.all_battles[bid] for bid in battle_response.json().get('battle_ids', []) if
- bid in self.citizen.all_battles]
+ battle_response = self._req.get(f"{self.url}/api/v1/battles/{country.id}")
+ return [
+ self.citizen.all_battles[bid] for bid in battle_response.json().get("battle_ids", []) if bid in self.citizen.all_battles
+ ]
except: # noqa
return []
def fetch_tasks(self) -> List[Dict[str, Any]]:
try:
- task_response = self._req.post(
- f'{self.url}/api/v1/command', data=dict(citizen=self.citizen_id, key=self.key)).json()
- if task_response.get('status'):
- return task_response.get('data')
+ task_response = self._req.post(f"{self.url}/api/v1/command", data=dict(citizen=self.citizen_id, key=self.key)).json()
+ if task_response.get("status"):
+ return task_response.get("data")
else:
return []
except: # noqa
@@ -722,13 +856,20 @@ class BattleSide:
points: int
deployed: List[constants.Country]
allies: List[constants.Country]
- battle: 'Battle'
+ battle: "Battle"
_battle: weakref.ReferenceType
country: constants.Country
is_defender: bool
- def __init__(self, battle: 'Battle', country: constants.Country, points: int, allies: List[constants.Country],
- deployed: List[constants.Country], defender: bool):
+ def __init__(
+ self,
+ battle: "Battle",
+ country: constants.Country,
+ points: int,
+ allies: List[constants.Country],
+ deployed: List[constants.Country],
+ defender: bool,
+ ):
self._battle = weakref.ref(battle)
self.country = country
self.points = points
@@ -741,11 +882,11 @@ class BattleSide:
return self.country.id
def __repr__(self):
- side_text = 'Defender' if self.is_defender else 'Invader '
+ side_text = "Defender" if self.is_defender else "Invader "
return f"2d}p>"
def __str__(self):
- side_text = 'Defender' if self.is_defender else 'Invader '
+ side_text = "Defender" if self.is_defender else "Invader "
return f"{side_text} {self.country.name} - {self.points:>2d} points"
def __format__(self, format_spec):
@@ -753,8 +894,7 @@ class BattleSide:
@property
def as_dict(self) -> Dict[str, Union[int, constants.Country, bool, List[constants.Country]]]:
- return dict(points=self.points, country=self.country, is_defender=self.is_defender, allies=self.allies,
- deployed=self.deployed)
+ return dict(points=self.points, country=self.country, is_defender=self.is_defender, allies=self.allies, deployed=self.deployed)
@property
def battle(self):
@@ -771,13 +911,14 @@ class BattleDivision:
inv_medal: Dict[str, int]
terrain: int
div: int
- battle: 'Battle'
+ battle: "Battle"
_battle: weakref.ReferenceType
@property
def as_dict(self):
- return dict(id=self.id, division=self.div, terrain=(self.terrain, self.terrain_display), wall=self.wall,
- epic=self.epic, end=self.div_end)
+ return dict(
+ id=self.id, division=self.div, terrain=(self.terrain, self.terrain_display), wall=self.wall, epic=self.epic, end=self.div_end
+ )
@property
def is_air(self):
@@ -787,8 +928,17 @@ class BattleDivision:
def div_end(self) -> bool:
return utils.now() >= self.end
- def __init__(self, battle: 'Battle', div_id: int, end: datetime.datetime, epic: bool, div: int, wall_for: int,
- wall_dom: float, terrain_id: int = 0):
+ def __init__(
+ self,
+ battle: "Battle",
+ div_id: int,
+ end: datetime.datetime,
+ epic: bool,
+ div: int,
+ wall_for: int,
+ wall_dom: float,
+ terrain_id: int = 0,
+ ):
"""Battle division helper class
:type div_id: int
@@ -803,7 +953,7 @@ class BattleDivision:
self.id = div_id
self.end = end
self.epic = epic
- self.wall = {'for': wall_for, 'dom': wall_dom}
+ self.wall = {"for": wall_for, "dom": wall_dom}
self.terrain = terrain_id
self.div = div
@@ -816,7 +966,7 @@ class BattleDivision:
if self.terrain:
base_name += f" ({self.terrain_display})"
if self.div_end:
- base_name += ' Ended'
+ base_name += " Ended"
return base_name
def __repr__(self):
@@ -842,9 +992,18 @@ class Battle:
@property
def as_dict(self):
- return dict(id=self.id, war_id=self.war_id, divisions=self.div, zone=self.zone_id, rw=self.is_rw,
- dict_lib=self.is_dict_lib, start=self.start, sides={'inv': self.invader, 'def': self.defender},
- region=[self.region_id, self.region_name], link=self.link)
+ return dict(
+ id=self.id,
+ war_id=self.war_id,
+ divisions=self.div,
+ zone=self.zone_id,
+ rw=self.is_rw,
+ dict_lib=self.is_dict_lib,
+ start=self.start,
+ sides={"inv": self.invader, "def": self.defender},
+ region=[self.region_id, self.region_name],
+ link=self.link,
+ )
@property
def has_air(self) -> bool:
@@ -874,43 +1033,52 @@ class Battle:
:param battle: Dict object for single battle from '/military/campaignsJson/list' response's 'battles' object
"""
- self.id = int(battle.get('id'))
- self.war_id = int(battle.get('war_id'))
- self.zone_id = int(battle.get('zone_id'))
- 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.region_id = battle.get('region', {}).get('id')
- self.region_name = battle.get('region', {}).get('name')
- self.start = datetime.datetime.fromtimestamp(int(battle.get('start', 0)), tz=constants.erep_tz)
+ self.id = int(battle.get("id"))
+ self.war_id = int(battle.get("war_id"))
+ self.zone_id = int(battle.get("zone_id"))
+ 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.region_id = battle.get("region", {}).get("id")
+ self.region_name = battle.get("region", {}).get("name")
+ self.start = datetime.datetime.fromtimestamp(int(battle.get("start", 0)), tz=constants.erep_tz)
self.invader = BattleSide(
- self, constants.COUNTRIES[battle.get('inv', {}).get('id')], battle.get('inv', {}).get('points'),
- [constants.COUNTRIES[row.get('id')] for row in battle.get('inv', {}).get('ally_list')],
- [constants.COUNTRIES[row.get('id')] for row in battle.get('inv', {}).get('ally_list') if row['deployed']],
- False
+ self,
+ constants.COUNTRIES[battle.get("inv", {}).get("id")],
+ battle.get("inv", {}).get("points"),
+ [constants.COUNTRIES[row.get("id")] for row in battle.get("inv", {}).get("ally_list")],
+ [constants.COUNTRIES[row.get("id")] for row in battle.get("inv", {}).get("ally_list") if row["deployed"]],
+ False,
)
self.defender = BattleSide(
- self, constants.COUNTRIES[battle.get('def', {}).get('id')], battle.get('def', {}).get('points'),
- [constants.COUNTRIES[row.get('id')] for row in battle.get('def', {}).get('ally_list')],
- [constants.COUNTRIES[row.get('id')] for row in battle.get('def', {}).get('ally_list') if row['deployed']],
- True
+ self,
+ constants.COUNTRIES[battle.get("def", {}).get("id")],
+ battle.get("def", {}).get("points"),
+ [constants.COUNTRIES[row.get("id")] for row in battle.get("def", {}).get("ally_list")],
+ [constants.COUNTRIES[row.get("id")] for row in battle.get("def", {}).get("ally_list") if row["deployed"]],
+ True,
)
self.div = {}
- for div, data in battle.get('div', {}).items():
+ for div, data in battle.get("div", {}).items():
div = int(div)
- if data.get('end'):
- end = datetime.datetime.fromtimestamp(data.get('end'), tz=constants.erep_tz)
+ if data.get("end"):
+ end = datetime.datetime.fromtimestamp(data.get("end"), tz=constants.erep_tz)
else:
end = constants.max_datetime
- battle_div = BattleDivision(self, div_id=data.get('id'), div=data.get('div'), end=end,
- epic=data.get('epic_type') in [1, 5],
- wall_for=data.get('wall').get('for'),
- wall_dom=data.get('wall').get('dom'),
- terrain_id=data.get('terrain', 0))
+ battle_div = BattleDivision(
+ self,
+ div_id=data.get("id"),
+ div=data.get("div"),
+ end=end,
+ epic=data.get("epic_type") in [1, 5],
+ wall_for=data.get("wall").get("for"),
+ wall_dom=data.get("wall").get("dom"),
+ terrain_id=data.get("terrain", 0),
+ )
self.div.update({div: battle_div})
@@ -922,8 +1090,10 @@ class Battle:
else:
time_part = f"-{self.start - time_now}"
- return (f"Battle {self.id} for {self.region_name[:16]:16} | "
- f"{self.invader} : {self.defender} | Round time {time_part} | {'R'+str(self.zone_id):>3}")
+ return (
+ f"Battle {self.id} for {self.region_name[:16]:16} | "
+ f"{self.invader} : {self.defender} | Round time {time_part} | {'R'+str(self.zone_id):>3}"
+ )
def __repr__(self):
return f""
@@ -981,9 +1151,16 @@ class TelegramReporter:
@property
def as_dict(self):
- return {'chat_id': self.chat_id, 'api_url': self.api_url, 'player': self.player_name,
- 'last_time': self._last_time, 'next_time': self._next_time, 'queue': self.__queue,
- 'initialized': self.__initialized, 'has_threads': not self._threads}
+ return {
+ "chat_id": self.chat_id,
+ "api_url": self.api_url,
+ "player": self.player_name,
+ "last_time": self._last_time,
+ "next_time": self._next_time,
+ "queue": self.__queue,
+ "initialized": self.__initialized,
+ "has_threads": not self._threads,
+ }
def do_init(self, chat_id: int, token: str = None, player_name: str = None):
if token is None:
@@ -995,7 +1172,7 @@ class TelegramReporter:
self._last_time = utils.good_timedelta(utils.now(), datetime.timedelta(minutes=-5))
self._last_full_energy_report = utils.good_timedelta(utils.now(), datetime.timedelta(minutes=-30))
if self.__queue:
- self.send_message('Telegram initialized')
+ self.send_message("Telegram initialized")
def send_message(self, message: str) -> bool:
self.__queue.append(message)
@@ -1020,22 +1197,27 @@ class TelegramReporter:
self.send_message(message)
def report_medal(self, msg, multiple: bool = True):
- new_line = '\n' if multiple else ''
+ new_line = "\n" if multiple else ""
self.send_message(f"New award: {new_line}*{msg}*")
- def report_fight(self, battle: 'Battle', invader: bool, division: 'BattleDivision', damage: float, hits: int):
+ def report_fight(self, battle: "Battle", invader: bool, division: "BattleDivision", damage: float, hits: int):
side_txt = (battle.invader if invader else battle.defender).country.iso
- self.send_message(f"*Fight report*:\n{int(damage):,d} dmg ({hits} hits) in"
- f" [battle {battle.id} for {battle.region_name[:16]}]({battle.link}) in d{division.div} on "
- f"{side_txt} side")
+ self.send_message(
+ f"*Fight report*:\n{int(damage):,d} dmg ({hits} hits) in"
+ f" [battle {battle.id} for {battle.region_name[:16]}]({battle.link}) in d{division.div} on "
+ f"{side_txt} side"
+ )
def report_item_donation(self, citizen_id: int, amount: float, product: str):
- self.send_message(f"*Donation*: {amount} x {product} to citizen "
- f"[{citizen_id}](https://www.erepublik.com/en/citizen/profile/{citizen_id})")
+ self.send_message(
+ f"*Donation*: {amount} x {product} to citizen " f"[{citizen_id}](https://www.erepublik.com/en/citizen/profile/{citizen_id})"
+ )
def report_money_donation(self, citizen_id: int, amount: float, is_currency: bool = True):
- self.send_message(f"*Donation*: {amount}{'cc' if is_currency else 'gold'} to citizen "
- f"[{citizen_id}](https://www.erepublik.com/en/citizen/profile/{citizen_id})")
+ self.send_message(
+ f"*Donation*: {amount}{'cc' if is_currency else 'gold'} to citizen "
+ f"[{citizen_id}](https://www.erepublik.com/en/citizen/profile/{citizen_id})"
+ )
def __send_messages(self):
while self._next_time > utils.now():
@@ -1046,9 +1228,9 @@ class TelegramReporter:
message = "\n\n".join(self.__queue)
if self.player_name:
message = f"Player *{self.player_name}*\n\n" + message
- response = post(f"{self.api_url}/sendMessage", json=dict(chat_id=self.chat_id, text=message, parse_mode='Markdown'))
+ response = post(f"{self.api_url}/sendMessage", json=dict(chat_id=self.chat_id, text=message, parse_mode="Markdown"))
self._last_time = utils.now()
- if response.json().get('ok'):
+ if response.json().get("ok"):
self.__queue.clear()
return True
return False
@@ -1056,14 +1238,16 @@ class TelegramReporter:
def send_photos(self, photos: List[Tuple[str, BytesIO]]):
for photo_title, photo in photos:
photo.seek(0)
- post(f"https://{self.api_url}/sendPhoto",
- data=dict(chat_id=self.chat_id, caption=photo_title),
- files=[('photo', ("f{utils.slugify(photo_title)}.png", photo))])
+ post(
+ f"https://{self.api_url}/sendPhoto",
+ data=dict(chat_id=self.chat_id, caption=photo_title),
+ files=[("photo", ("f{utils.slugify(photo_title)}.png", photo))],
+ )
return
class OfferItem(NamedTuple):
- price: float = 999_999_999.
+ price: float = 999_999_999.0
country: constants.Country = constants.Country(0, "", "", "")
amount: int = 0
offer_id: int = 0
@@ -1090,5 +1274,6 @@ class Inventory:
@property
def as_dict(self) -> Dict[str, Union[types.InvFinal, types.InvRaw, int]]:
- return dict(active=self.active, final=self.final, boosters=self.boosters, raw=self.raw, offers=self.offers,
- total=self.total, used=self.used)
+ return dict(
+ active=self.active, final=self.final, boosters=self.boosters, raw=self.raw, offers=self.offers, total=self.total, used=self.used
+ )
diff --git a/erepublik/constants.py b/erepublik/constants.py
index 575cb63..4893ba5 100644
--- a/erepublik/constants.py
+++ b/erepublik/constants.py
@@ -3,10 +3,21 @@ from typing import Dict, Optional, Union
import pytz
-__all__ = ['erep_tz', 'min_datetime', 'max_datetime', 'Country', 'AIR_RANKS', 'COUNTRIES', 'FOOD_ENERGY',
- 'GROUND_RANKS', 'GROUND_RANK_POINTS', 'INDUSTRIES', 'TERRAINS']
+__all__ = [
+ "erep_tz",
+ "min_datetime",
+ "max_datetime",
+ "Country",
+ "AIR_RANKS",
+ "COUNTRIES",
+ "FOOD_ENERGY",
+ "GROUND_RANKS",
+ "GROUND_RANK_POINTS",
+ "INDUSTRIES",
+ "TERRAINS",
+]
-erep_tz = pytz.timezone('US/Pacific')
+erep_tz = pytz.timezone("US/Pacific")
min_datetime = erep_tz.localize(datetime.datetime(2007, 11, 20))
max_datetime = erep_tz.localize(datetime.datetime(2281, 9, 4))
@@ -53,18 +64,70 @@ class Country:
class Industries:
- __by_name = {'food': 1, 'weapon': 2, 'ticket': 3, 'house': 4, 'aircraft': 23,
- 'foodraw': 7, 'weaponraw': 12, 'houseraw': 18, 'aircraftraw': 24, 'airplaneraw': 24,
- 'frm': 7, 'wrm': 12, 'hrm': 18, 'arm': 24,
- 'frm q1': 7, 'frm q2': 8, 'frm q3': 9, 'frm q4': 10, 'frm q5': 11,
- 'wrm q1': 12, 'wrm q2': 13, 'wrm q3': 14, 'wrm q4': 15, 'wrm q5': 16,
- 'hrm q1': 18, 'hrm q2': 19, 'hrm q3': 20, 'hrm q4': 21, 'hrm q5': 22,
- 'arm q1': 24, 'arm q2': 25, 'arm q3': 26, 'arm q4': 27, 'arm q5': 28}
- __by_id = {1: 'Food', 2: 'Weapon', 3: 'Ticket', 4: 'House', 23: 'Aircraft',
- 7: 'foodRaw', 8: 'FRM q2', 9: 'FRM q3', 10: 'FRM q4', 11: 'FRM q5',
- 12: 'weaponRaw', 13: 'WRM q2', 14: 'WRM q3', 15: 'WRM q4', 16: 'WRM q5',
- 17: 'houseRaw', 18: 'houseRaw', 19: 'HRM q2', 20: 'HRM q3', 21: 'HRM q4', 22: 'HRM q5',
- 24: 'aircraftRaw', 25: 'ARM q2', 26: 'ARM q3', 27: 'ARM q4', 28: 'ARM q5'}
+ __by_name = {
+ "food": 1,
+ "weapon": 2,
+ "ticket": 3,
+ "house": 4,
+ "aircraft": 23,
+ "foodraw": 7,
+ "weaponraw": 12,
+ "houseraw": 18,
+ "aircraftraw": 24,
+ "airplaneraw": 24,
+ "frm": 7,
+ "wrm": 12,
+ "hrm": 18,
+ "arm": 24,
+ "frm q1": 7,
+ "frm q2": 8,
+ "frm q3": 9,
+ "frm q4": 10,
+ "frm q5": 11,
+ "wrm q1": 12,
+ "wrm q2": 13,
+ "wrm q3": 14,
+ "wrm q4": 15,
+ "wrm q5": 16,
+ "hrm q1": 18,
+ "hrm q2": 19,
+ "hrm q3": 20,
+ "hrm q4": 21,
+ "hrm q5": 22,
+ "arm q1": 24,
+ "arm q2": 25,
+ "arm q3": 26,
+ "arm q4": 27,
+ "arm q5": 28,
+ }
+ __by_id = {
+ 1: "Food",
+ 2: "Weapon",
+ 3: "Ticket",
+ 4: "House",
+ 23: "Aircraft",
+ 7: "foodRaw",
+ 8: "FRM q2",
+ 9: "FRM q3",
+ 10: "FRM q4",
+ 11: "FRM q5",
+ 12: "weaponRaw",
+ 13: "WRM q2",
+ 14: "WRM q3",
+ 15: "WRM q4",
+ 16: "WRM q5",
+ 17: "houseRaw",
+ 18: "houseRaw",
+ 19: "HRM q2",
+ 20: "HRM q3",
+ 21: "HRM q4",
+ 22: "HRM q5",
+ 24: "aircraftRaw",
+ 25: "ARM q2",
+ 26: "ARM q3",
+ 27: "ARM q4",
+ 28: "ARM q5",
+ }
def __getitem__(self, item) -> Optional[Union[int, str]]:
if isinstance(item, int):
@@ -144,110 +207,452 @@ class Rank:
AIR_RANK_NAMES: Dict[int, str] = {
- 1: 'Airman', 2: 'Airman 1st Class', 3: 'Airman 1st Class*', 4: 'Airman 1st Class**', 5: 'Airman 1st Class***', 6: 'Airman 1st Class****', 7: 'Airman 1st Class*****',
- 8: 'Senior Airman', 9: 'Senior Airman*', 10: 'Senior Airman**', 11: 'Senior Airman***', 12: 'Senior Airman****', 13: 'Senior Airman*****',
- 14: 'Staff Sergeant', 15: 'Staff Sergeant*', 16: 'Staff Sergeant**', 17: 'Staff Sergeant***', 18: 'Staff Sergeant****', 19: 'Staff Sergeant*****',
- 20: 'Aviator', 21: 'Aviator*', 22: 'Aviator**', 23: 'Aviator***', 24: 'Aviator****', 25: 'Aviator*****',
- 26: 'Flight Lieutenant', 27: 'Flight Lieutenant*', 28: 'Flight Lieutenant**', 29: 'Flight Lieutenant***', 30: 'Flight Lieutenant****', 31: 'Flight Lieutenant*****',
- 32: 'Squadron Leader', 33: 'Squadron Leader*', 34: 'Squadron Leader**', 35: 'Squadron Leader***', 36: 'Squadron Leader****', 37: 'Squadron Leader*****',
- 38: 'Chief Master Sergeant', 39: 'Chief Master Sergeant*', 40: 'Chief Master Sergeant**', 41: 'Chief Master Sergeant***', 42: 'Chief Master Sergeant****', 43: 'Chief Master Sergeant*****',
- 44: 'Wing Commander', 45: 'Wing Commander*', 46: 'Wing Commander**', 47: 'Wing Commander***', 48: 'Wing Commander****', 49: 'Wing Commander*****',
- 50: 'Group Captain', 51: 'Group Captain*', 52: 'Group Captain**', 53: 'Group Captain***', 54: 'Group Captain****', 55: 'Group Captain*****',
- 56: 'Air Commodore', 57: 'Air Commodore*', 58: 'Air Commodore**', 59: 'Air Commodore***', 60: 'Air Commodore****', 61: 'Air Commodore*****',
- 62: 'Air Vice Marshal', 63: 'Air Vice Marshal*', 64: 'Air Vice Marshal**', 65: 'Air Vice Marshal***', 66: 'Air Vice Marshal****', 67: 'Air Vice Marshal*****',
- 68: 'Air Marshal', 69: 'Air Marshal*', 70: 'Air Marshal**', 71: 'Air Marshal***', 72: 'Air Marshal****', 73: 'Air Marshal*****',
- 74: 'Air Chief Marshal', 75: 'Air Chief Marshal*', 76: 'Air Chief Marshal**', 77: 'Air Chief Marshal***', 78: 'Air Chief Marshal****', 79: 'Air Chief Marshal*****',
+ 1: "Airman",
+ 2: "Airman 1st Class",
+ 3: "Airman 1st Class*",
+ 4: "Airman 1st Class**",
+ 5: "Airman 1st Class***",
+ 6: "Airman 1st Class****",
+ 7: "Airman 1st Class*****",
+ 8: "Senior Airman",
+ 9: "Senior Airman*",
+ 10: "Senior Airman**",
+ 11: "Senior Airman***",
+ 12: "Senior Airman****",
+ 13: "Senior Airman*****",
+ 14: "Staff Sergeant",
+ 15: "Staff Sergeant*",
+ 16: "Staff Sergeant**",
+ 17: "Staff Sergeant***",
+ 18: "Staff Sergeant****",
+ 19: "Staff Sergeant*****",
+ 20: "Aviator",
+ 21: "Aviator*",
+ 22: "Aviator**",
+ 23: "Aviator***",
+ 24: "Aviator****",
+ 25: "Aviator*****",
+ 26: "Flight Lieutenant",
+ 27: "Flight Lieutenant*",
+ 28: "Flight Lieutenant**",
+ 29: "Flight Lieutenant***",
+ 30: "Flight Lieutenant****",
+ 31: "Flight Lieutenant*****",
+ 32: "Squadron Leader",
+ 33: "Squadron Leader*",
+ 34: "Squadron Leader**",
+ 35: "Squadron Leader***",
+ 36: "Squadron Leader****",
+ 37: "Squadron Leader*****",
+ 38: "Chief Master Sergeant",
+ 39: "Chief Master Sergeant*",
+ 40: "Chief Master Sergeant**",
+ 41: "Chief Master Sergeant***",
+ 42: "Chief Master Sergeant****",
+ 43: "Chief Master Sergeant*****",
+ 44: "Wing Commander",
+ 45: "Wing Commander*",
+ 46: "Wing Commander**",
+ 47: "Wing Commander***",
+ 48: "Wing Commander****",
+ 49: "Wing Commander*****",
+ 50: "Group Captain",
+ 51: "Group Captain*",
+ 52: "Group Captain**",
+ 53: "Group Captain***",
+ 54: "Group Captain****",
+ 55: "Group Captain*****",
+ 56: "Air Commodore",
+ 57: "Air Commodore*",
+ 58: "Air Commodore**",
+ 59: "Air Commodore***",
+ 60: "Air Commodore****",
+ 61: "Air Commodore*****",
+ 62: "Air Vice Marshal",
+ 63: "Air Vice Marshal*",
+ 64: "Air Vice Marshal**",
+ 65: "Air Vice Marshal***",
+ 66: "Air Vice Marshal****",
+ 67: "Air Vice Marshal*****",
+ 68: "Air Marshal",
+ 69: "Air Marshal*",
+ 70: "Air Marshal**",
+ 71: "Air Marshal***",
+ 72: "Air Marshal****",
+ 73: "Air Marshal*****",
+ 74: "Air Chief Marshal",
+ 75: "Air Chief Marshal*",
+ 76: "Air Chief Marshal**",
+ 77: "Air Chief Marshal***",
+ 78: "Air Chief Marshal****",
+ 79: "Air Chief Marshal*****",
}
AIR_RANK_POINTS: Dict[int, Optional[int]] = {
- 1: 0, 2: 10, 3: 25, 4: 45, 5: 70, 6: 100, 7: 140, 8: 190, 9: 270, 10: 380, 11: 530, 12: 850, 13: 1300, 14: 2340, 15: 3300, 16: 4200, 17: 5150, 18: 6100, 19: 7020, 20: 9100, 21: 12750, 22: 16400, 23: 20000, 24: 23650, 25: 27300,
- 26: 35500, 27: 48000, 28: 60000, 29: 72400, 30: 84500, 31: 97000, 32: 110000, 33: 140000, 34: 170000, 35: 210000, 36: 290000, 37: 350000, 38: 429000, 39: 601000, 40: 772000, 41: 944000, 42: 1115000, 43: 1287000,
- 44: 1673000, 45: 2238000, 46: 2804000, 47: 3369000, 48: 3935000, 49: 4500000, 50: 5020000, 51: 7028000, 52: 9036000, 53: 11044000, 54: 13052000, 55: 15060000,
- 56: 19580000, 57: 27412000, 58: 35244000, 59: 43076000, 60: 50908000, 61: 58740000, 62: 76360000, 63: 113166443, 64: 137448000, 65: None, 66: None, 67: None,
- 68: None, 69: None, 70: None, 71: None, 72: None, 73: None, 74: None, 75: None, 76: None, 77: None, 78: None, 79: None,
+ 1: 0,
+ 2: 10,
+ 3: 25,
+ 4: 45,
+ 5: 70,
+ 6: 100,
+ 7: 140,
+ 8: 190,
+ 9: 270,
+ 10: 380,
+ 11: 530,
+ 12: 850,
+ 13: 1300,
+ 14: 2340,
+ 15: 3300,
+ 16: 4200,
+ 17: 5150,
+ 18: 6100,
+ 19: 7020,
+ 20: 9100,
+ 21: 12750,
+ 22: 16400,
+ 23: 20000,
+ 24: 23650,
+ 25: 27300,
+ 26: 35500,
+ 27: 48000,
+ 28: 60000,
+ 29: 72400,
+ 30: 84500,
+ 31: 97000,
+ 32: 110000,
+ 33: 140000,
+ 34: 170000,
+ 35: 210000,
+ 36: 290000,
+ 37: 350000,
+ 38: 429000,
+ 39: 601000,
+ 40: 772000,
+ 41: 944000,
+ 42: 1115000,
+ 43: 1287000,
+ 44: 1673000,
+ 45: 2238000,
+ 46: 2804000,
+ 47: 3369000,
+ 48: 3935000,
+ 49: 4500000,
+ 50: 5020000,
+ 51: 7028000,
+ 52: 9036000,
+ 53: 11044000,
+ 54: 13052000,
+ 55: 15060000,
+ 56: 19580000,
+ 57: 27412000,
+ 58: 35244000,
+ 59: 43076000,
+ 60: 50908000,
+ 61: 58740000,
+ 62: 76360000,
+ 63: 113166443,
+ 64: 137448000,
+ 65: None,
+ 66: None,
+ 67: None,
+ 68: None,
+ 69: None,
+ 70: None,
+ 71: None,
+ 72: None,
+ 73: None,
+ 74: None,
+ 75: None,
+ 76: None,
+ 77: None,
+ 78: None,
+ 79: None,
}
AIR_RANKS: Dict[int, Rank] = {i: Rank(i, AIR_RANK_NAMES[i], AIR_RANK_POINTS[i], True) for i in range(1, 80)}
COUNTRIES: Dict[int, Country] = {
- 1: Country(1, 'Romania', 'Romania', 'ROU'), 9: Country(9, 'Brazil', 'Brazil', 'BRA'),
- 10: Country(10, 'Italy', 'Italy', 'ITA'), 11: Country(11, 'France', 'France', 'FRA'),
- 12: Country(12, 'Germany', 'Germany', 'DEU'), 13: Country(13, 'Hungary', 'Hungary', 'HUN'),
- 14: Country(14, 'China', 'China', 'CHN'), 15: Country(15, 'Spain', 'Spain', 'ESP'),
- 23: Country(23, 'Canada', 'Canada', 'CAN'), 24: Country(24, 'USA', 'USA', 'USA'),
- 26: Country(26, 'Mexico', 'Mexico', 'MEX'), 27: Country(27, 'Argentina', 'Argentina', 'ARG'),
- 28: Country(28, 'Venezuela', 'Venezuela', 'VEN'), 29: Country(29, 'United Kingdom', 'United-Kingdom', 'GBR'),
- 30: Country(30, 'Switzerland', 'Switzerland', 'CHE'), 31: Country(31, 'Netherlands', 'Netherlands', 'NLD'),
- 32: Country(32, 'Belgium', 'Belgium', 'BEL'), 33: Country(33, 'Austria', 'Austria', 'AUT'),
- 34: Country(34, 'Czech Republic', 'Czech-Republic', 'CZE'), 35: Country(35, 'Poland', 'Poland', 'POL'),
- 36: Country(36, 'Slovakia', 'Slovakia', 'SVK'), 37: Country(37, 'Norway', 'Norway', 'NOR'),
- 38: Country(38, 'Sweden', 'Sweden', 'SWE'), 39: Country(39, 'Finland', 'Finland', 'FIN'),
- 40: Country(40, 'Ukraine', 'Ukraine', 'UKR'), 41: Country(41, 'Russia', 'Russia', 'RUS'),
- 42: Country(42, 'Bulgaria', 'Bulgaria', 'BGR'), 43: Country(43, 'Turkey', 'Turkey', 'TUR'),
- 44: Country(44, 'Greece', 'Greece', 'GRC'), 45: Country(45, 'Japan', 'Japan', 'JPN'),
- 47: Country(47, 'South Korea', 'South-Korea', 'KOR'), 48: Country(48, 'India', 'India', 'IND'),
- 49: Country(49, 'Indonesia', 'Indonesia', 'IDN'), 50: Country(50, 'Australia', 'Australia', 'AUS'),
- 51: Country(51, 'South Africa', 'South-Africa', 'ZAF'),
- 52: Country(52, 'Republic of Moldova', 'Republic-of-Moldova', 'MDA'),
- 53: Country(53, 'Portugal', 'Portugal', 'PRT'), 54: Country(54, 'Ireland', 'Ireland', 'IRL'),
- 55: Country(55, 'Denmark', 'Denmark', 'DNK'), 56: Country(56, 'Iran', 'Iran', 'IRN'),
- 57: Country(57, 'Pakistan', 'Pakistan', 'PAK'), 58: Country(58, 'Israel', 'Israel', 'ISR'),
- 59: Country(59, 'Thailand', 'Thailand', 'THA'), 61: Country(61, 'Slovenia', 'Slovenia', 'SVN'),
- 63: Country(63, 'Croatia', 'Croatia', 'HRV'), 64: Country(64, 'Chile', 'Chile', 'CHL'),
- 65: Country(65, 'Serbia', 'Serbia', 'SRB'), 66: Country(66, 'Malaysia', 'Malaysia', 'MYS'),
- 67: Country(67, 'Philippines', 'Philippines', 'PHL'), 68: Country(68, 'Singapore', 'Singapore', 'SGP'),
- 69: Country(69, 'Bosnia and Herzegovina', 'Bosnia-Herzegovina', 'BiH'),
- 70: Country(70, 'Estonia', 'Estonia', 'EST'), 80: Country(80, 'Montenegro', 'Montenegro', 'MNE'),
- 71: Country(71, 'Latvia', 'Latvia', 'LVA'), 72: Country(72, 'Lithuania', 'Lithuania', 'LTU'),
- 73: Country(73, 'North Korea', 'North-Korea', 'PRK'), 74: Country(74, 'Uruguay', 'Uruguay', 'URY'),
- 75: Country(75, 'Paraguay', 'Paraguay', 'PRY'), 76: Country(76, 'Bolivia', 'Bolivia', 'BOL'),
- 77: Country(77, 'Peru', 'Peru', 'PER'), 78: Country(78, 'Colombia', 'Colombia', 'COL'),
- 79: Country(79, 'Republic of Macedonia (FYROM)', 'Republic-of-Macedonia-FYROM', 'MKD'),
- 81: Country(81, 'Republic of China (Taiwan)', 'Republic-of-China-Taiwan', 'TWN'),
- 82: Country(82, 'Cyprus', 'Cyprus', 'CYP'), 167: Country(167, 'Albania', 'Albania', 'ALB'),
- 83: Country(83, 'Belarus', 'Belarus', 'BLR'), 84: Country(84, 'New Zealand', 'New-Zealand', 'NZL'),
- 164: Country(164, 'Saudi Arabia', 'Saudi-Arabia', 'SAU'), 165: Country(165, 'Egypt', 'Egypt', 'EGY'),
- 166: Country(166, 'United Arab Emirates', 'United-Arab-Emirates', 'UAE'),
- 168: Country(168, 'Georgia', 'Georgia', 'GEO'), 169: Country(169, 'Armenia', 'Armenia', 'ARM'),
- 170: Country(170, 'Nigeria', 'Nigeria', 'NGA'), 171: Country(171, 'Cuba', 'Cuba', 'CUB')
+ 1: Country(1, "Romania", "Romania", "ROU"),
+ 9: Country(9, "Brazil", "Brazil", "BRA"),
+ 10: Country(10, "Italy", "Italy", "ITA"),
+ 11: Country(11, "France", "France", "FRA"),
+ 12: Country(12, "Germany", "Germany", "DEU"),
+ 13: Country(13, "Hungary", "Hungary", "HUN"),
+ 14: Country(14, "China", "China", "CHN"),
+ 15: Country(15, "Spain", "Spain", "ESP"),
+ 23: Country(23, "Canada", "Canada", "CAN"),
+ 24: Country(24, "USA", "USA", "USA"),
+ 26: Country(26, "Mexico", "Mexico", "MEX"),
+ 27: Country(27, "Argentina", "Argentina", "ARG"),
+ 28: Country(28, "Venezuela", "Venezuela", "VEN"),
+ 29: Country(29, "United Kingdom", "United-Kingdom", "GBR"),
+ 30: Country(30, "Switzerland", "Switzerland", "CHE"),
+ 31: Country(31, "Netherlands", "Netherlands", "NLD"),
+ 32: Country(32, "Belgium", "Belgium", "BEL"),
+ 33: Country(33, "Austria", "Austria", "AUT"),
+ 34: Country(34, "Czech Republic", "Czech-Republic", "CZE"),
+ 35: Country(35, "Poland", "Poland", "POL"),
+ 36: Country(36, "Slovakia", "Slovakia", "SVK"),
+ 37: Country(37, "Norway", "Norway", "NOR"),
+ 38: Country(38, "Sweden", "Sweden", "SWE"),
+ 39: Country(39, "Finland", "Finland", "FIN"),
+ 40: Country(40, "Ukraine", "Ukraine", "UKR"),
+ 41: Country(41, "Russia", "Russia", "RUS"),
+ 42: Country(42, "Bulgaria", "Bulgaria", "BGR"),
+ 43: Country(43, "Turkey", "Turkey", "TUR"),
+ 44: Country(44, "Greece", "Greece", "GRC"),
+ 45: Country(45, "Japan", "Japan", "JPN"),
+ 47: Country(47, "South Korea", "South-Korea", "KOR"),
+ 48: Country(48, "India", "India", "IND"),
+ 49: Country(49, "Indonesia", "Indonesia", "IDN"),
+ 50: Country(50, "Australia", "Australia", "AUS"),
+ 51: Country(51, "South Africa", "South-Africa", "ZAF"),
+ 52: Country(52, "Republic of Moldova", "Republic-of-Moldova", "MDA"),
+ 53: Country(53, "Portugal", "Portugal", "PRT"),
+ 54: Country(54, "Ireland", "Ireland", "IRL"),
+ 55: Country(55, "Denmark", "Denmark", "DNK"),
+ 56: Country(56, "Iran", "Iran", "IRN"),
+ 57: Country(57, "Pakistan", "Pakistan", "PAK"),
+ 58: Country(58, "Israel", "Israel", "ISR"),
+ 59: Country(59, "Thailand", "Thailand", "THA"),
+ 61: Country(61, "Slovenia", "Slovenia", "SVN"),
+ 63: Country(63, "Croatia", "Croatia", "HRV"),
+ 64: Country(64, "Chile", "Chile", "CHL"),
+ 65: Country(65, "Serbia", "Serbia", "SRB"),
+ 66: Country(66, "Malaysia", "Malaysia", "MYS"),
+ 67: Country(67, "Philippines", "Philippines", "PHL"),
+ 68: Country(68, "Singapore", "Singapore", "SGP"),
+ 69: Country(69, "Bosnia and Herzegovina", "Bosnia-Herzegovina", "BiH"),
+ 70: Country(70, "Estonia", "Estonia", "EST"),
+ 80: Country(80, "Montenegro", "Montenegro", "MNE"),
+ 71: Country(71, "Latvia", "Latvia", "LVA"),
+ 72: Country(72, "Lithuania", "Lithuania", "LTU"),
+ 73: Country(73, "North Korea", "North-Korea", "PRK"),
+ 74: Country(74, "Uruguay", "Uruguay", "URY"),
+ 75: Country(75, "Paraguay", "Paraguay", "PRY"),
+ 76: Country(76, "Bolivia", "Bolivia", "BOL"),
+ 77: Country(77, "Peru", "Peru", "PER"),
+ 78: Country(78, "Colombia", "Colombia", "COL"),
+ 79: Country(79, "Republic of Macedonia (FYROM)", "Republic-of-Macedonia-FYROM", "MKD"),
+ 81: Country(81, "Republic of China (Taiwan)", "Republic-of-China-Taiwan", "TWN"),
+ 82: Country(82, "Cyprus", "Cyprus", "CYP"),
+ 167: Country(167, "Albania", "Albania", "ALB"),
+ 83: Country(83, "Belarus", "Belarus", "BLR"),
+ 84: Country(84, "New Zealand", "New-Zealand", "NZL"),
+ 164: Country(164, "Saudi Arabia", "Saudi-Arabia", "SAU"),
+ 165: Country(165, "Egypt", "Egypt", "EGY"),
+ 166: Country(166, "United Arab Emirates", "United-Arab-Emirates", "UAE"),
+ 168: Country(168, "Georgia", "Georgia", "GEO"),
+ 169: Country(169, "Armenia", "Armenia", "ARM"),
+ 170: Country(170, "Nigeria", "Nigeria", "NGA"),
+ 171: Country(171, "Cuba", "Cuba", "CUB"),
}
FOOD_ENERGY: Dict[str, int] = dict(q1=2, q2=4, q3=6, q4=8, q5=10, q6=12, q7=20)
GROUND_RANK_NAMES: Dict[int, str] = {
- 1: 'Recruit', 2: 'Private', 3: 'Private*', 4: 'Private**', 5: 'Private***', 6: 'Corporal', 7: 'Corporal*', 8: 'Corporal**', 9: 'Corporal***',
- 10: 'Sergeant', 11: 'Sergeant*', 12: 'Sergeant**', 13: 'Sergeant***', 14: 'Lieutenant', 15: 'Lieutenant*', 16: 'Lieutenant**', 17: 'Lieutenant***',
- 18: 'Captain', 19: 'Captain*', 20: 'Captain**', 21: 'Captain***', 22: 'Major', 23: 'Major*', 24: 'Major**', 25: 'Major***',
- 26: 'Commander', 27: 'Commander*', 28: 'Commander**', 29: 'Commander***', 30: 'Lt Colonel', 31: 'Lt Colonel*', 32: 'Lt Colonel**', 33: 'Lt Colonel***',
- 34: 'Colonel', 35: 'Colonel*', 36: 'Colonel**', 37: 'Colonel***', 38: 'General', 39: 'General*', 40: 'General**', 41: 'General***',
- 42: 'Field Marshal', 43: 'Field Marshal*', 44: 'Field Marshal**', 45: 'Field Marshal***', 46: 'Supreme Marshal', 47: 'Supreme Marshal*', 48: 'Supreme Marshal**', 49: 'Supreme Marshal***',
- 50: 'National Force', 51: 'National Force*', 52: 'National Force**', 53: 'National Force***', 54: 'World Class Force', 55: 'World Class Force*', 56: 'World Class Force**', 57: 'World Class Force***',
- 58: 'Legendary Force', 59: 'Legendary Force*', 60: 'Legendary Force**', 61: 'Legendary Force***', 62: 'God of War', 63: 'God of War*', 64: 'God of War**', 65: 'God of War***',
- 66: 'Titan', 67: 'Titan*', 68: 'Titan**', 69: 'Titan***',
- 70: 'Legends I', 71: 'Legends II', 72: 'Legends III', 73: 'Legends IV', 74: 'Legends V', 75: 'Legends VI', 76: 'Legends VII', 77: 'Legends VIII', 78: 'Legends IX', 79: 'Legends X',
- 80: 'Legends XI', 81: 'Legends XII', 82: 'Legends XIII', 83: 'Legends XIV', 84: 'Legends XV', 85: 'Legends XVI', 86: 'Legends XVII', 87: 'Legends XVIII', 88: 'Legends XIX', 89: 'Legends XX'
+ 1: "Recruit",
+ 2: "Private",
+ 3: "Private*",
+ 4: "Private**",
+ 5: "Private***",
+ 6: "Corporal",
+ 7: "Corporal*",
+ 8: "Corporal**",
+ 9: "Corporal***",
+ 10: "Sergeant",
+ 11: "Sergeant*",
+ 12: "Sergeant**",
+ 13: "Sergeant***",
+ 14: "Lieutenant",
+ 15: "Lieutenant*",
+ 16: "Lieutenant**",
+ 17: "Lieutenant***",
+ 18: "Captain",
+ 19: "Captain*",
+ 20: "Captain**",
+ 21: "Captain***",
+ 22: "Major",
+ 23: "Major*",
+ 24: "Major**",
+ 25: "Major***",
+ 26: "Commander",
+ 27: "Commander*",
+ 28: "Commander**",
+ 29: "Commander***",
+ 30: "Lt Colonel",
+ 31: "Lt Colonel*",
+ 32: "Lt Colonel**",
+ 33: "Lt Colonel***",
+ 34: "Colonel",
+ 35: "Colonel*",
+ 36: "Colonel**",
+ 37: "Colonel***",
+ 38: "General",
+ 39: "General*",
+ 40: "General**",
+ 41: "General***",
+ 42: "Field Marshal",
+ 43: "Field Marshal*",
+ 44: "Field Marshal**",
+ 45: "Field Marshal***",
+ 46: "Supreme Marshal",
+ 47: "Supreme Marshal*",
+ 48: "Supreme Marshal**",
+ 49: "Supreme Marshal***",
+ 50: "National Force",
+ 51: "National Force*",
+ 52: "National Force**",
+ 53: "National Force***",
+ 54: "World Class Force",
+ 55: "World Class Force*",
+ 56: "World Class Force**",
+ 57: "World Class Force***",
+ 58: "Legendary Force",
+ 59: "Legendary Force*",
+ 60: "Legendary Force**",
+ 61: "Legendary Force***",
+ 62: "God of War",
+ 63: "God of War*",
+ 64: "God of War**",
+ 65: "God of War***",
+ 66: "Titan",
+ 67: "Titan*",
+ 68: "Titan**",
+ 69: "Titan***",
+ 70: "Legends I",
+ 71: "Legends II",
+ 72: "Legends III",
+ 73: "Legends IV",
+ 74: "Legends V",
+ 75: "Legends VI",
+ 76: "Legends VII",
+ 77: "Legends VIII",
+ 78: "Legends IX",
+ 79: "Legends X",
+ 80: "Legends XI",
+ 81: "Legends XII",
+ 82: "Legends XIII",
+ 83: "Legends XIV",
+ 84: "Legends XV",
+ 85: "Legends XVI",
+ 86: "Legends XVII",
+ 87: "Legends XVIII",
+ 88: "Legends XIX",
+ 89: "Legends XX",
}
GROUND_RANK_POINTS: Dict[int, int] = {
- 1: 0, 2: 15, 3: 45, 4: 80, 5: 120, 6: 170, 7: 250, 8: 350, 9: 450, 10: 600, 11: 800, 12: 1000,
- 13: 1400, 14: 1850, 15: 2350, 16: 3000, 17: 3750, 18: 5000, 19: 6500, 20: 9000, 21: 12000,
- 22: 15500, 23: 20000, 24: 25000, 25: 31000, 26: 40000, 27: 52000, 28: 67000, 29: 85000,
- 30: 110000, 31: 140000, 32: 180000, 33: 225000, 34: 285000, 35: 355000, 36: 435000, 37: 540000,
- 38: 660000, 39: 800000, 40: 950000, 41: 1140000, 42: 1350000, 43: 1600000, 44: 1875000,
- 45: 2185000, 46: 2550000, 47: 3000000, 48: 3500000, 49: 4150000, 50: 4900000, 51: 5800000,
- 52: 7000000, 53: 9000000, 54: 11500000, 55: 14500000, 56: 18000000, 57: 22000000, 58: 26500000,
- 59: 31500000, 60: 37000000, 61: 43000000, 62: 50000000, 63: 100000000, 64: 200000000,
- 65: 500000000, 66: 1000000000, 67: 2000000000, 68: 4000000000, 69: 10000000000, 70: 20000000000,
- 71: 30000000000, 72: 40000000000, 73: 50000000000, 74: 60000000000, 75: 70000000000,
- 76: 80000000000, 77: 90000000000, 78: 100000000000, 79: 110000000000, 80: 120000000000,
- 81: 130000000000, 82: 140000000000, 83: 150000000000, 84: 160000000000, 85: 170000000000,
- 86: 180000000000, 87: 190000000000, 88: 200000000000, 89: 210000000000
+ 1: 0,
+ 2: 15,
+ 3: 45,
+ 4: 80,
+ 5: 120,
+ 6: 170,
+ 7: 250,
+ 8: 350,
+ 9: 450,
+ 10: 600,
+ 11: 800,
+ 12: 1000,
+ 13: 1400,
+ 14: 1850,
+ 15: 2350,
+ 16: 3000,
+ 17: 3750,
+ 18: 5000,
+ 19: 6500,
+ 20: 9000,
+ 21: 12000,
+ 22: 15500,
+ 23: 20000,
+ 24: 25000,
+ 25: 31000,
+ 26: 40000,
+ 27: 52000,
+ 28: 67000,
+ 29: 85000,
+ 30: 110000,
+ 31: 140000,
+ 32: 180000,
+ 33: 225000,
+ 34: 285000,
+ 35: 355000,
+ 36: 435000,
+ 37: 540000,
+ 38: 660000,
+ 39: 800000,
+ 40: 950000,
+ 41: 1140000,
+ 42: 1350000,
+ 43: 1600000,
+ 44: 1875000,
+ 45: 2185000,
+ 46: 2550000,
+ 47: 3000000,
+ 48: 3500000,
+ 49: 4150000,
+ 50: 4900000,
+ 51: 5800000,
+ 52: 7000000,
+ 53: 9000000,
+ 54: 11500000,
+ 55: 14500000,
+ 56: 18000000,
+ 57: 22000000,
+ 58: 26500000,
+ 59: 31500000,
+ 60: 37000000,
+ 61: 43000000,
+ 62: 50000000,
+ 63: 100000000,
+ 64: 200000000,
+ 65: 500000000,
+ 66: 1000000000,
+ 67: 2000000000,
+ 68: 4000000000,
+ 69: 10000000000,
+ 70: 20000000000,
+ 71: 30000000000,
+ 72: 40000000000,
+ 73: 50000000000,
+ 74: 60000000000,
+ 75: 70000000000,
+ 76: 80000000000,
+ 77: 90000000000,
+ 78: 100000000000,
+ 79: 110000000000,
+ 80: 120000000000,
+ 81: 130000000000,
+ 82: 140000000000,
+ 83: 150000000000,
+ 84: 160000000000,
+ 85: 170000000000,
+ 86: 180000000000,
+ 87: 190000000000,
+ 88: 200000000000,
+ 89: 210000000000,
}
GROUND_RANKS: Dict[int, Rank] = {i: Rank(i, GROUND_RANK_NAMES[i], GROUND_RANK_POINTS[i], False) for i in range(1, 90)}
INDUSTRIES = Industries()
-TERRAINS: Dict[int, str] = {0: 'Standard', 1: 'Industrial', 2: 'Urban', 3: 'Suburbs', 4: 'Airport', 5: 'Plains',
- 6: 'Wasteland', 7: 'Mountains', 8: 'Beach', 9: 'Swamp', 10: 'Mud', 11: 'Hills',
- 12: 'Jungle', 13: 'Forest', 14: 'Desert'}
+TERRAINS: Dict[int, str] = {
+ 0: "Standard",
+ 1: "Industrial",
+ 2: "Urban",
+ 3: "Suburbs",
+ 4: "Airport",
+ 5: "Plains",
+ 6: "Wasteland",
+ 7: "Mountains",
+ 8: "Beach",
+ 9: "Swamp",
+ 10: "Mud",
+ 11: "Hills",
+ 12: "Jungle",
+ 13: "Forest",
+ 14: "Desert",
+}
diff --git a/erepublik/utils.py b/erepublik/utils.py
index 151b90e..58ffe73 100644
--- a/erepublik/utils.py
+++ b/erepublik/utils.py
@@ -23,10 +23,33 @@ except ImportError:
import json
__all__ = [
- 'VERSION', 'calculate_hit', 'date_from_eday', 'eday_from_date', 'deprecation', 'get_final_hit_dmg', 'write_file',
- 'get_air_hit_dmg_value', 'get_file', 'get_ground_hit_dmg_value', 'get_sleep_seconds', 'good_timedelta', 'slugify',
- 'interactive_sleep', 'json', 'localize_dt', 'localize_timestamp', 'normalize_html_json', 'now', 'silent_sleep',
- 'json_decode_object_hook', 'json_load', 'json_loads', 'json_dump', 'json_dumps', 'b64json', 'ErepublikJSONEncoder',
+ "VERSION",
+ "calculate_hit",
+ "date_from_eday",
+ "eday_from_date",
+ "deprecation",
+ "get_final_hit_dmg",
+ "write_file",
+ "get_air_hit_dmg_value",
+ "get_file",
+ "get_ground_hit_dmg_value",
+ "get_sleep_seconds",
+ "good_timedelta",
+ "slugify",
+ "interactive_sleep",
+ "json",
+ "localize_dt",
+ "localize_timestamp",
+ "normalize_html_json",
+ "now",
+ "silent_sleep",
+ "json_decode_object_hook",
+ "json_load",
+ "json_loads",
+ "json_dump",
+ "json_dumps",
+ "b64json",
+ "ErepublikJSONEncoder",
]
VERSION: str = __version__
@@ -75,7 +98,7 @@ def date_from_eday(eday: int) -> datetime.date:
def get_sleep_seconds(time_until: datetime.datetime) -> int:
- """ time_until aware datetime object Wrapper for sleeping until """
+ """time_until aware datetime object Wrapper for sleeping until"""
sleep_seconds = int((time_until - now()).total_seconds())
return sleep_seconds if sleep_seconds > 0 else 0
@@ -107,7 +130,7 @@ def get_file(filepath: str) -> str:
file = Path(filepath)
if file.exists():
if file.is_dir():
- return str(file / 'new_file.txt')
+ return str(file / "new_file.txt")
else:
version = 1
try:
@@ -129,16 +152,16 @@ def get_file(filepath: str) -> str:
def write_file(filename: str, content: str) -> int:
filename = get_file(filename)
- with open(filename, 'ab') as f:
+ with open(filename, "ab") as f:
ret = f.write(content.encode("utf-8"))
return ret
def normalize_html_json(js: str) -> str:
- js = re.sub(r' \'(.*?)\'', lambda a: f'"{a.group(1)}"', js)
- js = re.sub(r'(\d\d):(\d\d):(\d\d)', r'\1\2\3', js)
+ js = re.sub(r" \'(.*?)\'", lambda a: f'"{a.group(1)}"', js)
+ js = re.sub(r"(\d\d):(\d\d):(\d\d)", r"\1\2\3", js)
js = re.sub(r'([{\s,])(\w+)(:)(?!"})', r'\1"\2"\3', js)
- js = re.sub(r',\s*}', '}', js)
+ js = re.sub(r",\s*}", "}", js)
return js
@@ -151,47 +174,51 @@ def slugify(value, allow_unicode=False) -> str:
"""
value = str(value)
if allow_unicode:
- value = unicodedata.normalize('NFKC', value)
+ value = unicodedata.normalize("NFKC", value)
else:
- value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
- value = re.sub(r'[^\w\s-]', '_', value).strip().lower()
- return re.sub(r'[-\s]+', '-', value)
+ value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
+ value = re.sub(r"[^\w\s-]", "_", value).strip().lower()
+ return re.sub(r"[-\s]+", "-", value)
-def calculate_hit(strength: float, rang: int, tp: bool, elite: bool, ne: bool, booster: int = 0,
- weapon: int = 200, is_deploy: bool = False) -> Decimal:
+def calculate_hit(
+ strength: float, rang: int, tp: bool, elite: bool, ne: bool, booster: int = 0, weapon: int = 200, is_deploy: bool = False
+) -> Decimal:
dec = 3 if is_deploy else 0
- base_str = (1 + Decimal(str(round(strength, 3))) / 400)
- base_rnk = (1 + Decimal(str(rang / 5)))
- base_wpn = (1 + Decimal(str(weapon / 100)))
+ base_str = 1 + Decimal(str(round(strength, 3))) / 400
+ base_rnk = 1 + Decimal(str(rang / 5))
+ base_wpn = 1 + Decimal(str(weapon / 100))
dmg = 10 * base_str * base_rnk * base_wpn
dmg = get_final_hit_dmg(dmg, rang, tp=tp, elite=elite, ne=ne, booster=booster)
return Decimal(round(dmg, dec))
-def get_ground_hit_dmg_value(citizen_id: int, natural_enemy: bool = False, true_patriot: bool = False,
- booster: int = 0, weapon_power: int = 200) -> Decimal:
- r = requests.get(f'https://www.erepublik.com/en/main/citizen-profile-json/{citizen_id}').json()
- rang = r['military']['militaryData']['ground']['rankNumber']
- strength = r['military']['militaryData']['ground']['strength']
- elite = r['citizenAttributes']['level'] > 100
+def get_ground_hit_dmg_value(
+ citizen_id: int, natural_enemy: bool = False, true_patriot: bool = False, booster: int = 0, weapon_power: int = 200
+) -> Decimal:
+ r = requests.get(f"https://www.erepublik.com/en/main/citizen-profile-json/{citizen_id}").json()
+ rang = r["military"]["militaryData"]["ground"]["rankNumber"]
+ strength = r["military"]["militaryData"]["ground"]["strength"]
+ elite = r["citizenAttributes"]["level"] > 100
if natural_enemy:
true_patriot = True
return calculate_hit(strength, rang, true_patriot, elite, natural_enemy, booster, weapon_power)
-def get_air_hit_dmg_value(citizen_id: int, natural_enemy: bool = False, true_patriot: bool = False, booster: int = 0,
- weapon_power: int = 0) -> Decimal:
- r = requests.get(f'https://www.erepublik.com/en/main/citizen-profile-json/{citizen_id}').json()
- rang = r['military']['militaryData']['aircraft']['rankNumber']
- elite = r['citizenAttributes']['level'] > 100
+def get_air_hit_dmg_value(
+ citizen_id: int, natural_enemy: bool = False, true_patriot: bool = False, booster: int = 0, weapon_power: int = 0
+) -> Decimal:
+ r = requests.get(f"https://www.erepublik.com/en/main/citizen-profile-json/{citizen_id}").json()
+ rang = r["military"]["militaryData"]["aircraft"]["rankNumber"]
+ elite = r["citizenAttributes"]["level"] > 100
return calculate_hit(0, rang, true_patriot, elite, natural_enemy, booster, weapon_power)
-def get_final_hit_dmg(base_dmg: Union[Decimal, float, str], rang: int,
- tp: bool = False, elite: bool = False, ne: bool = False, booster: int = 0) -> Decimal:
+def get_final_hit_dmg(
+ base_dmg: Union[Decimal, float, str], rang: int, tp: bool = False, elite: bool = False, ne: bool = False, booster: int = 0
+) -> Decimal:
dmg = Decimal(str(base_dmg))
if elite:
@@ -211,23 +238,23 @@ def deprecation(message):
def json_decode_object_hook(
o: Union[Dict[str, Any], List[Any], int, float, str]
) -> Union[Dict[str, Any], List[Any], int, float, str, datetime.date, datetime.datetime, datetime.timedelta]:
- """ Convert classes.ErepublikJSONEncoder datetime, date and timedelta to their python objects
+ """Convert classes.ErepublikJSONEncoder datetime, date and timedelta to their python objects
:param o:
:return: Union[Dict[str, Any], List[Any], int, float, str, datetime.date, datetime.datetime, datetime.timedelta]
"""
- if o.get('__type__'):
- _type = o.get('__type__')
- if _type == 'datetime':
- dt = datetime.datetime.strptime(f"{o['date']} {o['time']}", '%Y-%m-%d %H:%M:%S')
- if o.get('tzinfo'):
- dt = pytz.timezone(o['tzinfo']).localize(dt)
+ if o.get("__type__"):
+ _type = o.get("__type__")
+ if _type == "datetime":
+ dt = datetime.datetime.strptime(f"{o['date']} {o['time']}", "%Y-%m-%d %H:%M:%S")
+ if o.get("tzinfo"):
+ dt = pytz.timezone(o["tzinfo"]).localize(dt)
return dt
- elif _type == 'date':
- dt = datetime.datetime.strptime(f"{o['date']}", '%Y-%m-%d')
+ elif _type == "date":
+ dt = datetime.datetime.strptime(f"{o['date']}", "%Y-%m-%d")
return dt.date()
- elif _type == 'timedelta':
- return datetime.timedelta(seconds=o['total_seconds'])
+ elif _type == "timedelta":
+ return datetime.timedelta(seconds=o["total_seconds"])
return o
@@ -242,20 +269,20 @@ def json_loads(s: str, **kwargs):
def json_dump(obj, fp, *args, **kwargs):
- if not kwargs.get('cls'):
+ if not kwargs.get("cls"):
kwargs.update(cls=ErepublikJSONEncoder)
return json.dump(obj, fp, *args, **kwargs)
def json_dumps(obj, *args, **kwargs):
- if not kwargs.get('cls'):
+ if not kwargs.get("cls"):
kwargs.update(cls=ErepublikJSONEncoder)
return json.dumps(obj, *args, **kwargs)
def b64json(obj: Union[Dict[str, Union[int, List[str]]], List[str]]):
if isinstance(obj, list):
- return b64encode(json.dumps(obj, separators=(',', ':')).encode('utf-8')).decode('utf-8')
+ return b64encode(json.dumps(obj, separators=(",", ":")).encode("utf-8")).decode("utf-8")
elif isinstance(obj, (int, str)):
return obj
elif isinstance(obj, dict):
@@ -263,27 +290,34 @@ def b64json(obj: Union[Dict[str, Union[int, List[str]]], List[str]]):
obj[k] = b64json(v)
else:
from .classes import ErepublikException
- raise ErepublikException(f'Unhandled object type! obj is {type(obj)}')
- return b64encode(json.dumps(obj, separators=(',', ':')).encode('utf-8')).decode('utf-8')
+
+ raise ErepublikException(f"Unhandled object type! obj is {type(obj)}")
+ return b64encode(json.dumps(obj, separators=(",", ":")).encode("utf-8")).decode("utf-8")
class ErepublikJSONEncoder(json.JSONEncoder):
def default(self, o):
try:
from erepublik.citizen import Citizen
+
if isinstance(o, Decimal):
return float(f"{o:.02f}")
elif isinstance(o, datetime.datetime):
- return dict(__type__='datetime', date=o.strftime("%Y-%m-%d"), time=o.strftime("%H:%M:%S"),
- tzinfo=str(o.tzinfo) if o.tzinfo else None)
+ return dict(
+ __type__="datetime",
+ date=o.strftime("%Y-%m-%d"),
+ time=o.strftime("%H:%M:%S"),
+ tzinfo=str(o.tzinfo) if o.tzinfo else None,
+ )
elif isinstance(o, datetime.date):
- return dict(__type__='date', date=o.strftime("%Y-%m-%d"))
+ return dict(__type__="date", date=o.strftime("%Y-%m-%d"))
elif isinstance(o, datetime.timedelta):
- return dict(__type__='timedelta', days=o.days, seconds=o.seconds,
- microseconds=o.microseconds, total_seconds=o.total_seconds())
+ return dict(
+ __type__="timedelta", days=o.days, seconds=o.seconds, microseconds=o.microseconds, total_seconds=o.total_seconds()
+ )
elif isinstance(o, Response):
- return dict(headers=dict(o.__dict__['headers']), url=o.url, text=o.text, status_code=o.status_code)
- elif hasattr(o, 'as_dict'):
+ return dict(headers=dict(o.__dict__["headers"]), url=o.url, text=o.text, status_code=o.status_code)
+ elif hasattr(o, "as_dict"):
return o.as_dict
elif isinstance(o, set):
return list(o)
@@ -291,7 +325,7 @@ class ErepublikJSONEncoder(json.JSONEncoder):
return o.to_json()
elif isinstance(o, Logger):
return str(o)
- elif hasattr(o, '__dict__'):
+ elif hasattr(o, "__dict__"):
return o.__dict__
else:
return super().default(o)
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..7e28eca
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,4 @@
+[tool.black]
+line-length = 140
+target-version = ['py38', 'py39']
+
diff --git a/setup.cfg b/setup.cfg
index 5b8808e..5ea24ba 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -19,11 +19,13 @@ universal = 1
[flake8]
exclude = docs,.git,log,debug,venv
-max-line-length = 240
-ignore = D100,D101,D102,D103
+line_length = 140
+max-line-length = 140
+ignore = D100,D101,D102,D103,E203
[pycodestyle]
-max-line-length = 240
+line_length = 140
+max-line-length = 140
exclude = .git,log,debug,venv, build
[mypy]
@@ -36,4 +38,4 @@ warn_unused_configs = True
[isort]
multi_line_output = 2
-line_length = 240
+line_length = 140
diff --git a/tests/test_erepublik_script.py b/tests/test_erepublik_script.py
index 8950dd8..d830d5e 100644
--- a/tests/test_erepublik_script.py
+++ b/tests/test_erepublik_script.py
@@ -17,14 +17,13 @@ class TestErepublik(unittest.TestCase):
self.citizen.config.interactive = False
def test_should_do_levelup(self):
- self.citizen.energy.recovered = 1900
- self.citizen.energy.recoverable = 2940
+ self.citizen.energy.energy = 5950
self.citizen.energy.interval = 30
- self.citizen.energy.limit = 3000
+ self.citizen.energy.limit = 6000
self.citizen.details.xp = 14850
self.assertTrue(self.citizen.should_do_levelup)
- self.citizen.energy.recoverable = 1000
+ self.citizen.energy.energy = 1000
self.assertFalse(self.citizen.should_do_levelup)
def test_should_travel_to_fight(self):
@@ -33,40 +32,38 @@ class TestErepublik(unittest.TestCase):
self.citizen.config.always_travel = False
self.assertFalse(self.citizen.should_travel_to_fight())
- self.citizen.energy.recovered = 1900
- self.citizen.energy.recoverable = 2940
+ self.citizen.energy.energy = 5960
self.citizen.energy.interval = 30
- self.citizen.energy.limit = 3000
+ self.citizen.energy.limit = 6000
self.citizen.details.xp = 14850
self.assertTrue(self.citizen.should_travel_to_fight())
self.citizen.details.xp = 15000
+ self.citizen.energy.energy = 5000
self.assertFalse(self.citizen.should_travel_to_fight())
- self.citizen.energy.recovered = 3000
- self.citizen.energy.recoverable = 2910
+ self.citizen.energy.energy = 5910
self.assertTrue(self.citizen.should_travel_to_fight())
- self.citizen.energy.recoverable = 2900
+ self.citizen.energy.energy = 5900
self.assertFalse(self.citizen.should_travel_to_fight())
# self.citizen.next_reachable_energy and self.citizen.config.next_energy
self.citizen.config.next_energy = True
- self.citizen.energy.limit = 5000
+ self.citizen.energy.limit = 10000
self.citizen.details.next_pp = [5000, 5250, 5750, 6250, 6750]
self.citizen.details.pp = 4900
- self.citizen.energy.recovered = 4000
- self.citizen.energy.recoverable = 4510
+ self.citizen.energy.energy = 8510
self.assertEqual(self.citizen.next_reachable_energy, 850)
- self.citizen.energy.recoverable = 4490
+ self.citizen.energy.energy = 8490
self.assertTrue(self.citizen.should_travel_to_fight())
self.assertEqual(self.citizen.next_reachable_energy, 350)
- self.citizen.energy.recovered = 100
- self.citizen.energy.recoverable = 150
+ self.citizen.energy.energy = 250
self.assertFalse(self.citizen.should_travel_to_fight())
self.assertEqual(self.citizen.next_reachable_energy, 0)
def test_should_fight(self):
def is_wc_close():
return self.citizen.max_time_till_full_ff > self.citizen.time_till_week_change
+
self.citizen.config.fight = False
self.assertEqual(self.citizen.should_fight(), (0, "Fighting not allowed!", False))
@@ -76,62 +73,64 @@ class TestErepublik(unittest.TestCase):
self.citizen.energy.limit = 3000
self.citizen.details.xp = 24705
if not is_wc_close:
- self.assertEqual(self.citizen.should_fight(), (0, 'Level up', False))
+ self.assertEqual(self.citizen.should_fight(), (0, "Level up", False))
- self.citizen.energy.recovered = 3000
- self.citizen.energy.recoverable = 2950
+ self.citizen.energy.energy = 5950
self.citizen.energy.interval = 30
- self.assertEqual(self.citizen.should_fight(), (900, 'Level up', True))
+ self.assertEqual(self.citizen.should_fight(), (900, "Level up", True))
self.citizen.my_companies.ff_lockdown = 160
- self.assertEqual(self.citizen.should_fight(), (900, 'Level up', True))
+ self.assertEqual(self.citizen.should_fight(), (900, "Level up", True))
self.citizen.my_companies.ff_lockdown = 0
# Level up reachable
self.citizen.details.xp = 24400
- self.assertEqual(self.citizen.should_fight(), (305, 'Fighting for close Levelup. Doing 305 hits', True))
+ self.assertEqual(self.citizen.should_fight(), (305, "Fighting for close Levelup. Doing 305 hits", True))
self.citizen.my_companies.ff_lockdown = 160
- self.assertEqual(self.citizen.should_fight(), (305, 'Fighting for close Levelup. Doing 305 hits', True))
+ self.assertEqual(self.citizen.should_fight(), (305, "Fighting for close Levelup. Doing 305 hits", True))
self.citizen.my_companies.ff_lockdown = 0
self.citizen.details.xp = 21000
- self.assertEqual(self.citizen.should_fight(), (75, 'Obligatory fighting for at least 75pp', True))
+ self.assertEqual(self.citizen.should_fight(), (75, "Obligatory fighting for at least 75pp", True))
self.citizen.my_companies.ff_lockdown = 160
- self.assertEqual(self.citizen.should_fight(), (75, 'Obligatory fighting for at least 75pp', True))
+ self.assertEqual(self.citizen.should_fight(), (75, "Obligatory fighting for at least 75pp", True))
self.citizen.my_companies.ff_lockdown = 0
self.citizen.details.pp = 80
# All-in (type = all-in and full ff)
self.citizen.config.all_in = True
- self.assertEqual(self.citizen.should_fight(), (595, 'Fighting all-in. Doing 595 hits', False))
+ self.assertEqual(self.citizen.should_fight(), (595, "Fighting all-in. Doing 595 hits", False))
self.citizen.my_companies.ff_lockdown = 160
- self.assertEqual(self.citizen.should_fight(), (
- 435, 'Fight count modified (old count: 595 | FF: 595 | WAM ff_lockdown: 160 | New count: 435)', False
- ))
+ self.assertEqual(
+ self.citizen.should_fight(),
+ (435, "Fight count modified (old count: 595 | FF: 595 | WAM ff_lockdown: 160 | New count: 435)", False),
+ )
self.citizen.my_companies.ff_lockdown = 0
self.citizen.config.air = True
- self.citizen.energy.recoverable = 1000
- self.assertEqual(self.citizen.should_fight(), (400, 'Fighting all-in in AIR. Doing 400 hits', False))
+ self.citizen.energy.energy = 4000
+ self.assertEqual(self.citizen.should_fight(), (400, "Fighting all-in in AIR. Doing 400 hits", False))
self.citizen.my_companies.ff_lockdown = 160
- self.assertEqual(self.citizen.should_fight(), (
- 240, 'Fight count modified (old count: 400 | FF: 400 | WAM ff_lockdown: 160 | New count: 240)', False
- ))
+ self.assertEqual(
+ self.citizen.should_fight(),
+ (240, "Fight count modified (old count: 400 | FF: 400 | WAM ff_lockdown: 160 | New count: 240)", False),
+ )
self.citizen.my_companies.ff_lockdown = 0
self.citizen.config.all_in = False
self.citizen.config.next_energy = True
- self.citizen.energy.limit = 5000
+ self.citizen.energy.limit = 10000
self.citizen.details.next_pp = [100, 150, 250, 400, 500]
- self.assertEqual(self.citizen.should_fight(), (320, 'Fighting for +1 energy. Doing 320 hits', False))
+ self.assertEqual(self.citizen.should_fight(), (320, "Fighting for +1 energy. Doing 320 hits", False))
self.citizen.my_companies.ff_lockdown = 160
- self.assertEqual(self.citizen.should_fight(), (
- 160, 'Fight count modified (old count: 320 | FF: 400 | WAM ff_lockdown: 160 | New count: 160)', False
- ))
+ self.assertEqual(
+ self.citizen.should_fight(),
+ (160, "Fight count modified (old count: 320 | FF: 400 | WAM ff_lockdown: 160 | New count: 160)", False),
+ )
self.citizen.my_companies.ff_lockdown = 0
self.citizen.energy.limit = 3000
self.citizen.details.next_pp = [19250, 20000]
self.citizen.config.next_energy = False
# 1h worth of energy
- self.citizen.energy.recoverable = 2910
- self.assertEqual(self.citizen.should_fight(), (30, 'Fighting for 1h energy. Doing 30 hits', True))
+ self.citizen.energy.energy = 5910
+ self.assertEqual(self.citizen.should_fight(), (30, "Fighting for 1h energy. Doing 30 hits", True))