Compare commits

...

50 Commits

Author SHA1 Message Date
7fadeb1a49 Bump version: 0.21.3 → 0.21.4 2020-09-21 11:26:51 +03:00
b723660f23 Fixups and type checks 2020-09-21 11:26:32 +03:00
f10eeec498 requirement update 2020-09-21 11:24:01 +03:00
230167f93d mypy bugfix 2020-09-21 11:23:43 +03:00
d5ed989e80 Bump version: 0.21.2.2 → 0.21.3 2020-08-18 16:37:27 +03:00
6fc24b8adf requirements 2020-08-18 16:37:07 +03:00
cf797f2f60 Fixes and updates 2020-08-18 13:14:41 +03:00
ad29045ace Bump version: 0.21.2.1 → 0.21.2.2 2020-07-29 11:40:41 +03:00
c919e46af5 PoliticsAPI extended and bugfixed 2020-07-29 11:40:32 +03:00
644b4d70e1 Bump version: 0.21.2 → 0.21.2.1 2020-07-29 11:23:31 +03:00
6dbbd054ba bugfix 2020-07-29 09:27:02 +03:00
0ee952e504 bugfix 2020-07-29 09:21:49 +03:00
bb9b198a53 Bump version: 0.21.1 → 0.21.2 2020-07-28 19:34:19 +03:00
cb22e631ca Merge branch 'memory-optimisation'
* memory-optimisation:
  Company cleanup optimisation
  JSON.dump sort_keys parameter throwing mysterious errors
  Fixed memory leak in Battle and MyCompanies classes
2020-07-28 19:33:52 +03:00
c43e20c8f6 Return all Non-Terrain divisions and their bh damage 2020-07-28 19:33:30 +03:00
c8f41b97af Company cleanup optimisation 2020-07-28 19:25:22 +03:00
d483bcbcb9 JSON.dump sort_keys parameter throwing mysterious errors 2020-07-28 18:29:25 +03:00
a316f277fb Fixed memory leak in Battle and MyCompanies classes 2020-07-28 18:28:03 +03:00
e8c81d17e6 Weapons kind should be singular - 'weapon' 2020-07-19 07:56:15 +03:00
edb4d8851b Bump version: 0.21.0.3 → 0.21.1 2020-07-16 11:15:04 +03:00
76edd6bb7d Update traveling to incorporate travel cooldown (1travel / 15sec) 2020-07-16 11:14:35 +03:00
8da376b852 Change variable names to be more precise if argument must be and id or instance (battle/battle_id, division/division_id) 2020-07-16 11:13:29 +03:00
b6b0be7442 Minimize error reporting locals to not duplicate instance.json data 2020-07-16 11:11:35 +03:00
ed434b605d Refactor '.format()' calls to f-strings 2020-07-16 11:08:31 +03:00
2bd311def6 Dev requirement update 2020-07-14 15:37:59 +03:00
4b437c2ba6 Update README.rst 2020-07-14 14:11:20 +03:00
cc8a1450d4 Merge pull request #3 from codacy-badger/codacy-badge
Add a Codacy badge to README.rst
2020-07-14 14:08:45 +03:00
0c9f3756ea Add Codacy badge 2020-07-14 11:07:36 +00:00
9de07950b8 Bump version: 0.21.0.2 → 0.21.0.3 2020-07-13 11:24:29 +03:00
766b7b2d95 bugfix 2020-07-12 10:45:44 +03:00
c730981865 Bump version: 0.21.0.1 → 0.21.0.2 2020-07-11 10:21:21 +03:00
d70c3e2c9e Typos 2020-07-11 10:21:12 +03:00
d044af6d2f Bump version: 0.21.0 → 0.21.0.1 2020-07-11 10:08:09 +03:00
dd75b10d2f missing __hash__ 2020-07-11 09:54:23 +03:00
a45dd7e0c3 Bump version: 0.20.4 → 0.21.0 2020-07-11 09:39:25 +03:00
316a826c93 Merge branch 'master' of github.com:eeriks/erepublik 2020-07-11 09:38:20 +03:00
c9710733e2 Typo 2020-07-11 09:37:22 +03:00
9e678d6b51 Bump version: 0.20.3.11 → 0.20.4 2020-07-10 17:13:15 +03:00
88517cb076 Bugfix 2020-07-10 17:09:28 +03:00
01c8aef012 Bugfix: South Africa link 2020-07-10 17:08:58 +03:00
d7ac66bd69 Bump version: 0.20.3.10 → 0.20.3.11 2020-07-10 12:16:53 +03:00
e8739caca1 fix 2020-07-10 12:16:18 +03:00
9df9c1cd87 Bump version: 0.20.3.9 → 0.20.3.10 2020-07-10 00:47:42 +03:00
1b004f163a bugfix 2020-07-10 00:47:36 +03:00
72bd2787d3 Bump version: 0.20.3.8 → 0.20.3.9 2020-07-09 19:11:04 +03:00
bfa6cb1e78 bugfix 2020-07-09 19:10:55 +03:00
1db7c98b47 Bump version: 0.20.3.7 → 0.20.3.8 2020-07-09 18:51:09 +03:00
1f21a71c74 bugfix 2020-07-09 18:51:00 +03:00
0531c8997b Bump version: 0.20.3.6 → 0.20.3.7 2020-07-09 17:42:24 +03:00
5a8a0a3920 mavericks 2020-07-09 17:42:15 +03:00
12 changed files with 488 additions and 395 deletions

View File

@ -88,9 +88,3 @@ dist: clean ## builds source and wheel package
install: clean ## install the package to the active Python's site-packages install: clean ## install the package to the active Python's site-packages
python setup.py install python setup.py install
setcommit:
bash set_commit_id.sh
# commit=`git log -1 --pretty=format:%h`
# sed -i.bak -E "s|COMMIT_ID = \".+\"|COMMIT_ID = \"$(commit)\"|g" erepublik/utils.py
# mv erepublik/utils.py.bak erepublik/utils.py

View File

@ -10,6 +10,10 @@ eRepublik script
:target: https://erepublik.readthedocs.io/en/latest/?badge=latest :target: https://erepublik.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status :alt: Documentation Status
.. image:: https://api.codacy.com/project/badge/Grade/eaa7ae43d23f4c0abab65c3bde89475a
:target: https://app.codacy.com/manual/eeriks/erepublik?utm_source=github.com&utm_medium=referral&utm_content=eeriks/erepublik&utm_campaign=Badge_Grade_Dashboard
:alt: Codacy Badge
Python package for automated eRepublik playing Python package for automated eRepublik playing
@ -30,3 +34,4 @@ This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypack
.. _Cookiecutter: https://github.com/audreyr/cookiecutter .. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage .. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage

View File

@ -4,8 +4,7 @@
__author__ = """Eriks Karls""" __author__ = """Eriks Karls"""
__email__ = 'eriks@72.lv' __email__ = 'eriks@72.lv'
__version__ = '0.20.3.6' __version__ = '0.21.4'
__commit_id__ = "ffbbd25"
from erepublik import classes, utils, constants from erepublik import classes, utils, constants
from erepublik.citizen import Citizen from erepublik.citizen import Citizen

View File

@ -15,24 +15,26 @@ class SlowRequests(Session):
timeout = datetime.timedelta(milliseconds=500) timeout = datetime.timedelta(milliseconds=500)
uas = [ uas = [
# Chrome # Chrome
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36', # noqa
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36', # noqa 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36', # noqa
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36', # noqa 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36', # noqa
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', # noqa 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', # noqa
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
# FireFox # FireFox
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0', 'Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0', 'Mozilla/5.0 (X11; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0',
] ]
debug = False debug = False
@ -113,12 +115,13 @@ class SlowRequests(Session):
class CitizenBaseAPI: class CitizenBaseAPI:
url: str = "https://www.erepublik.com/en" url: str = "https://www.erepublik.com/en"
_req: SlowRequests = None _req: SlowRequests
token: str = "" token: str
def __init__(self): def __init__(self):
""" Class for unifying eRepublik known endpoints and their required/optional parameters """ """ Class for unifying eRepublik known endpoints and their required/optional parameters """
self._req = SlowRequests() self._req = SlowRequests()
self.token = ""
def post(self, url: str, data=None, json=None, **kwargs) -> Response: def post(self, url: str, data=None, json=None, **kwargs) -> Response:
return self._req.post(url, data, json, **kwargs) return self._req.post(url, data, json, **kwargs)
@ -132,23 +135,23 @@ class CitizenBaseAPI:
class ErepublikAnniversaryAPI(CitizenBaseAPI): class ErepublikAnniversaryAPI(CitizenBaseAPI):
def _post_main_collect_anniversary_reward(self) -> Response: def _post_main_collect_anniversary_reward(self) -> Response:
return self.post("{}/main/collect-anniversary-reward".format(self.url), data={"_token": self.token}) return self.post(f"{self.url}/main/collect-anniversary-reward", data={"_token": self.token})
# 12th anniversary endpoints # 12th anniversary endpoints
def _get_anniversary_quest_data(self) -> Response: def _get_anniversary_quest_data(self) -> Response:
return self.get("{}/main/anniversaryQuestData".format(self.url)) return self.get(f"{self.url}/main/anniversaryQuestData")
def _post_map_rewards_unlock(self, node_id: int) -> Response: def _post_map_rewards_unlock(self, node_id: int) -> Response:
data = {'nodeId': node_id, '_token': self.token} data = {'nodeId': node_id, '_token': self.token}
return self.post("{}/main/map-rewards-unlock".format(self.url), data=data) return self.post(f"{self.url}/main/map-rewards-unlock", data=data)
def _post_map_rewards_speedup(self, node_id: int, currency_amount: int) -> Response: def _post_map_rewards_speedup(self, node_id: int, currency_amount: int) -> Response:
data = {'nodeId': node_id, '_token': self.token, "currencyCost": currency_amount} data = {'nodeId': node_id, '_token': self.token, "currencyCost": currency_amount}
return self.post("{}/main/map-rewards-speedup".format(self.url), data=data) return self.post(f"{self.url}/main/map-rewards-speedup", data=data)
def _post_map_rewards_claim(self, node_id: int) -> Response: def _post_map_rewards_claim(self, node_id: int) -> Response:
data = {'nodeId': node_id, '_token': self.token} data = {'nodeId': node_id, '_token': self.token}
return self.post("{}/main/map-rewards-claim".format(self.url), data=data) return self.post(f"{self.url}/main/map-rewards-claim", data=data)
def _post_main_wheel_of_fortune_spin(self, cost) -> Response: def _post_main_wheel_of_fortune_spin(self, cost) -> Response:
return self.post(f"{self.url}/wheeloffortune-spin", data={'_token': self.token, "cost": cost}) return self.post(f"{self.url}/wheeloffortune-spin", data={'_token': self.token, "cost": cost})
@ -159,52 +162,52 @@ class ErepublikAnniversaryAPI(CitizenBaseAPI):
class ErepublikArticleAPI(CitizenBaseAPI): class ErepublikArticleAPI(CitizenBaseAPI):
def _get_main_article_json(self, article_id: int) -> Response: def _get_main_article_json(self, article_id: int) -> Response:
return self.get("{}/main/articleJson/{}".format(self.url, article_id)) return self.get(f"{self.url}/main/articleJson/{article_id}")
def _post_main_article_comments(self, article: int, page: int = 1) -> Response: def _post_main_article_comments(self, article_id: int, page: int = 1) -> Response:
data = dict(_token=self.token, articleId=article, page=page) data = dict(_token=self.token, articleId=article_id, page=page)
if page: if page:
data.update({'page': page}) data.update({'page': page})
return self.post("{}/main/articleComments".format(self.url), data=data) return self.post(f"{self.url}/main/articleComments", data=data)
def _post_main_article_comments_create(self, message: str, article: int, parent: int = 0) -> Response: def _post_main_article_comments_create(self, message: str, article_id: int, parent: int = 0) -> Response:
data = dict(_token=self.token, message=message, articleId=article) data = dict(_token=self.token, message=message, articleId=article_id)
if parent: if parent:
data.update({"parentId": parent}) data.update({"parentId": parent})
return self.post("{}/main/articleComments/create".format(self.url), data=data) return self.post(f"{self.url}/main/articleComments/create", data=data)
def _post_main_donate_article(self, article_id: int, amount: int) -> Response: def _post_main_donate_article(self, article_id: int, amount: int) -> Response:
data = dict(_token=self.token, articleId=article_id, amount=amount) data = dict(_token=self.token, articleId=article_id, amount=amount)
return self.post("{}/main/donate-article".format(self.url), data=data) return self.post(f"{self.url}/main/donate-article", data=data)
def _post_main_write_article(self, title: str, content: str, country: int, kind: int) -> Response: def _post_main_write_article(self, title: str, content: str, country_id: int, kind_id: int) -> Response:
data = dict(_token=self.token, article_name=title, article_body=content, article_location=country, data = dict(_token=self.token, article_name=title, article_body=content, article_location=country_id,
article_category=kind) article_category=kind_id)
return self.post("{}/main/write-article".format(self.url), data=data) return self.post(f"{self.url}/main/write-article", data=data)
def _post_main_vote_article(self, article_id: int) -> Response: def _post_main_vote_article(self, article_id: int) -> Response:
data = dict(_token=self.token, articleId=article_id) data = dict(_token=self.token, articleId=article_id)
return self.post("{}/main/vote-article".format(self.url), data=data) return self.post(f"{self.url}/main/vote-article", data=data)
class ErepublikCompanyAPI(CitizenBaseAPI): class ErepublikCompanyAPI(CitizenBaseAPI):
def _post_economy_assign_to_holding(self, factory: int, holding: int) -> Response: def _post_economy_assign_to_holding(self, factory_id: int, holding_id: int) -> Response:
data = dict(_token=self.token, factoryId=factory, action="assign", holdingCompanyId=holding) data = dict(_token=self.token, factoryId=factory_id, action="assign", holdingCompanyId=holding_id)
return self.post("{}/economy/assign-to-holding".format(self.url), data=data) return self.post(f"{self.url}/economy/assign-to-holding", data=data)
def _post_economy_create_company(self, industry: int, building_type: int = 1) -> Response: def _post_economy_create_company(self, industry_id: int, building_type: int = 1) -> Response:
data = {"_token": self.token, "company[industry_id]": industry, "company[building_type]": building_type} data = {"_token": self.token, "company[industry_id]": industry_id, "company[building_type]": building_type}
return self.post("{}/economy/create-company".format(self.url), data=data, return self.post(f"{self.url}/economy/create-company", data=data,
headers={"Referer": "{}/economy/create-company".format(self.url)}) headers={"Referer": f"{self.url}/economy/create-company"})
def _get_economy_inventory_items(self) -> Response: def _get_economy_inventory_items(self) -> Response:
return self.get("{}/economy/inventory-items/".format(self.url)) return self.get(f"{self.url}/economy/inventory-items/")
def _get_economy_job_market_json(self, country: int) -> Response: def _get_economy_job_market_json(self, country_id: int) -> Response:
return self.get("{}/economy/job-market-json/{}/1/desc".format(self.url, country)) return self.get(f"{self.url}/economy/job-market-json/{country_id}/1/desc")
def _get_economy_my_companies(self) -> Response: def _get_economy_my_companies(self) -> Response:
return self.get("{}/economy/myCompanies".format(self.url)) return self.get(f"{self.url}/economy/myCompanies")
def _post_economy_train(self, tg_ids: List[int]) -> Response: def _post_economy_train(self, tg_ids: List[int]) -> Response:
data: Dict[str, Union[int, str]] = {} data: Dict[str, Union[int, str]] = {}
@ -213,11 +216,11 @@ class ErepublikCompanyAPI(CitizenBaseAPI):
data["grounds[%i][train]" % idx] = 1 data["grounds[%i][train]" % idx] = 1
if data: if data:
data['_token'] = self.token data['_token'] = self.token
return self.post("{}/economy/train".format(self.url), data=data) return self.post(f"{self.url}/economy/train", data=data)
def _post_economy_upgrade_company(self, factory: int, level: int, pin: str = None) -> Response: def _post_economy_upgrade_company(self, factory: int, level: int, pin: str = None) -> Response:
data = dict(_token=self.token, type="upgrade", companyId=factory, level=level, pin="" if pin is None else pin) data = dict(_token=self.token, type="upgrade", companyId=factory, level=level, pin="" if pin is None else pin)
return self.post("{}/economy/upgrade-company".format(self.url), data=data) return self.post(f"{self.url}/economy/upgrade-company", data=data)
def _post_economy_work(self, action_type: str, wam: List[int] = None, employ: Dict[int, int] = None) -> Response: def _post_economy_work(self, action_type: str, wam: List[int] = None, employ: Dict[int, int] = None) -> Response:
data: Dict[str, Union[int, str]] = dict(action_type=action_type, _token=self.token) data: Dict[str, Union[int, str]] = dict(action_type=action_type, _token=self.token)
@ -241,174 +244,169 @@ class ErepublikCompanyAPI(CitizenBaseAPI):
f"companies[{max_idx}][own_work]": 0 f"companies[{max_idx}][own_work]": 0
}) })
max_idx += 1 max_idx += 1
return self.post("{}/economy/work".format(self.url), data=data) return self.post(f"{self.url}/economy/work", data=data)
def _post_economy_work_overtime(self) -> Response: def _post_economy_work_overtime(self) -> Response:
data = dict(action_type="workOvertime", _token=self.token) data = dict(action_type="workOvertime", _token=self.token)
return self.post("{}/economy/workOvertime".format(self.url), data=data) return self.post(f"{self.url}/economy/workOvertime", data=data)
def _post_economy_job_market_apply(self, citizen: int, salary: float) -> Response: def _post_economy_job_market_apply(self, citizen_id: int, salary: float) -> Response:
data = dict(_token=self.token, citizenId=citizen, salary=salary) data = dict(_token=self.token, citizenId=citizen_id, salary=salary)
return self.post("{}/economy/job-market-apply".format(self.url), data=data) return self.post(f"{self.url}/economy/job-market-apply", data=data)
def _post_economy_resign(self) -> Response: def _post_economy_resign(self) -> Response:
return self.post("{}/economy/resign".format(self.url), return self.post(f"{self.url}/economy/resign",
headers={"Content-Type": "application/x-www-form-urlencoded"}, headers={"Content-Type": "application/x-www-form-urlencoded"},
data={"_token": self.token, "action_type": "resign"}) data={"_token": self.token, "action_type": "resign"})
def _post_economy_sell_company(self, factory: int, pin: int = None, sell: bool = True) -> Response: def _post_economy_sell_company(self, factory_id: int, pin: int = None, sell: bool = True) -> Response:
data = dict(_token=self.token, pin="" if pin is None else pin) data = dict(_token=self.token, pin="" if pin is None else pin)
if sell: if sell:
data.update({"sell": "sell"}) data.update({"sell": "sell"})
else: else:
data.update({"dissolve": factory}) data.update({"dissolve": factory_id})
return self.post("{}/economy/sell-company/{}".format(self.url, factory), return self.post(f"{self.url}/economy/sell-company/{factory_id}",
data=data, headers={"Referer": self.url}) data=data, headers={"Referer": self.url})
class ErepublikCountryAPI(CitizenBaseAPI): class ErepublikCountryAPI(CitizenBaseAPI):
def _get_country_military(self, country: str) -> Response: def _get_country_military(self, country_name: str) -> Response:
return self.get("{}/country/military/{}".format(self.url, country)) return self.get(f"{self.url}/country/military/{country_name}")
def _post_main_country_donate(self, country: int, action: str, value: Union[int, float], def _post_main_country_donate(self, country_id: int, action: str, value: Union[int, float],
quality: int = None) -> Response: quality: int = None) -> Response:
json = dict(countryId=country, action=action, _token=self.token, value=value, quality=quality)
return self.post("{}/main/country-donate".format(self.url), data=json, data = dict(countryId=country_id, action=action, _token=self.token, value=value, quality=quality)
headers={"Referer": "{}/country/economy/Latvia".format(self.url)}) return self.post(f"{self.url}/main/country-donate", data=data,
headers={"Referer": f"{self.url}/country/economy/Latvia"})
class ErepublikEconomyAPI(CitizenBaseAPI): class ErepublikEconomyAPI(CitizenBaseAPI):
def _get_economy_citizen_accounts(self, organisation_id: int) -> Response: def _get_economy_citizen_accounts(self, organisation_id: int) -> Response:
return self.get("{}/economy/citizen-accounts/{}".format(self.url, organisation_id)) return self.get(f"{self.url}/economy/citizen-accounts/{organisation_id}")
def _get_economy_my_market_offers(self) -> Response: def _get_economy_my_market_offers(self) -> Response:
return self.get("{}/economy/myMarketOffers".format(self.url)) return self.get(f"{self.url}/economy/myMarketOffers")
def _get_main_job_data(self) -> Response: def _get_main_job_data(self) -> Response:
return self.get("{}/main/job-data".format(self.url)) return self.get(f"{self.url}/main/job-data")
def _post_main_buy_gold_items(self, currency: str, item: str, amount: int) -> Response: def _post_main_buy_gold_items(self, currency: str, item: str, amount: int) -> Response:
data = dict(itemId=item, currency=currency, amount=amount, _token=self.token) data = dict(itemId=item, currency=currency, amount=amount, _token=self.token)
return self.post("{}/main/buyGoldItems".format(self.url), data=data) return self.post(f"{self.url}/main/buyGoldItems", data=data)
def _post_economy_activate_booster(self, quality: int, duration: int, kind: str) -> Response: def _post_economy_activate_booster(self, quality: int, duration: int, kind: str) -> Response:
data = dict(type=kind, quality=quality, duration=duration, fromInventory=True) data = dict(type=kind, quality=quality, duration=duration, fromInventory=True)
return self.post("{}/economy/activateBooster".format(self.url), data=data) return self.post(f"{self.url}/economy/activateBooster", data=data)
def _post_economy_activate_house(self, quality: int) -> Response: def _post_economy_activate_house(self, quality: int) -> Response:
data = {"action": "activate", "quality": quality, "type": "house", "_token": self.token} data = {"action": "activate", "quality": quality, "type": "house", "_token": self.token}
return self.post("{}/economy/activateHouse".format(self.url), data=data) return self.post(f"{self.url}/economy/activateHouse", data=data)
def _post_economy_donate_items_action(self, citizen: int, amount: int, industry: int, def _post_economy_donate_items_action(self, citizen_id: int, amount: int, industry: int,
quality: int) -> Response: quality: int) -> Response:
data = dict(citizen_id=citizen, amount=amount, industry_id=industry, quality=quality, _token=self.token) data = dict(citizen_id=citizen_id, amount=amount, industry_id=industry, quality=quality, _token=self.token)
return self.post("{}/economy/donate-items-action".format(self.url), data=data, return self.post(f"{self.url}/economy/donate-items-action", data=data,
headers={"Referer": "{}/economy/donate-items/{}".format(self.url, citizen)}) headers={"Referer": f"{self.url}/economy/donate-items/{citizen_id}"})
def _post_economy_donate_money_action(self, citizen: int, amount: float = 0.0, def _post_economy_donate_money_action(self, citizen_id: int, amount: float = 0.0,
currency: int = 62) -> Response: currency: int = 62) -> Response:
data = dict(citizen_id=citizen, _token=self.token, currency_id=currency, amount=amount) data = dict(citizen_id=citizen_id, _token=self.token, currency_id=currency, amount=amount)
return self.post("{}/economy/donate-money-action".format(self.url), data=data, return self.post(f"{self.url}/economy/donate-money-action", data=data,
headers={"Referer": "{}/economy/donate-money/{}".format(self.url, citizen)}) headers={"Referer": f"{self.url}/economy/donate-money/{citizen_id}"})
def _post_economy_exchange_purchase(self, amount: float, currency: int, offer: int) -> Response: def _post_economy_exchange_purchase(self, amount: float, currency: int, offer: int) -> Response:
data = dict(_token=self.token, amount=amount, currencyId=currency, offerId=offer) data = dict(_token=self.token, amount=amount, currencyId=currency, offerId=offer)
return self.post("{}/economy/exchange/purchase/".format(self.url), data=data) return self.post(f"{self.url}/economy/exchange/purchase/", data=data)
def _post_economy_exchange_retrieve(self, personal: bool, page: int, currency: int) -> Response: def _post_economy_exchange_retrieve(self, personal: bool, page: int, currency: int) -> Response:
data = dict(_token=self.token, personalOffers=int(personal), page=page, currencyId=currency) data = dict(_token=self.token, personalOffers=int(personal), page=page, currencyId=currency)
return self.post("{}/economy/exchange/retrieve/".format(self.url), data=data) return self.post(f"{self.url}/economy/exchange/retrieve/", data=data)
def _post_economy_game_tokens_market(self, action: str) -> Response: def _post_economy_game_tokens_market(self, action: str) -> Response:
assert action in ['retrieve', ] assert action in ['retrieve', ]
data = dict(_token=self.token, action=action) data = dict(_token=self.token, action=action)
return self.post("{}/economy/gameTokensMarketAjax".format(self.url), data=data) return self.post(f"{self.url}/economy/gameTokensMarketAjax", data=data)
def _post_economy_marketplace(self, country: int, industry: int, quality: int, def _post_economy_marketplace(self, country: int, industry: int, quality: int,
order_asc: bool = True) -> Response: order_asc: bool = True) -> Response:
data = dict(countryId=country, industryId=industry, quality=quality, ajaxMarket=1, data = dict(countryId=country, industryId=industry, quality=quality, ajaxMarket=1,
orderBy="price_asc" if order_asc else "price_desc", _token=self.token) orderBy="price_asc" if order_asc else "price_desc", _token=self.token)
return self.post("{}/economy/marketplaceAjax".format(self.url), data=data) return self.post(f"{self.url}/economy/marketplaceAjax", data=data)
def _post_economy_marketplace_actions(self, amount: int, buy: bool = False, **kwargs) -> Response: def _post_economy_marketplace_actions(self, amount: int, buy: bool = False, **kwargs) -> Response:
if buy: if buy:
data = dict(_token=self.token, offerId=kwargs['offer'], amount=amount, orderBy="price_asc", currentPage=1, data = dict(_token=self.token, offerId=kwargs['offer'], amount=amount, orderBy="price_asc", currentPage=1,
buyAction=1) buyAction=1)
else: else:
data = dict(_token=self.token, countryId=kwargs["country"], price=kwargs["price"], data = dict(_token=self.token, countryId=kwargs["country_id"], price=kwargs["price"],
industryId=kwargs["industry"], quality=kwargs["quality"], amount=amount, sellAction='postOffer') industryId=kwargs["industry"], quality=kwargs["quality"], amount=amount, sellAction='postOffer')
return self.post("{}/economy/marketplaceActions".format(self.url), data=data) return self.post(f"{self.url}/economy/marketplaceActions", data=data)
class ErepublikLeaderBoardAPI(CitizenBaseAPI): class ErepublikLeaderBoardAPI(CitizenBaseAPI):
def _get_main_leaderboards_damage_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response: def _get_main_leaderboards_damage_aircraft_rankings(self, country_id: int, weeks: int = 0, mu_id: int = 0) -> Response:
data = (country, weeks, mu) return self.get(f"{self.url}/main/leaderboards-damage-aircraft-rankings/{country_id}/{weeks}/{mu_id}/0")
return self.get("{}/main/leaderboards-damage-aircraft-rankings/{}/{}/{}/0".format(self.url, *data))
def _get_main_leaderboards_damage_rankings(self, country: int, weeks: int = 0, mu: int = 0, def _get_main_leaderboards_damage_rankings(self, country_id: int, weeks: int = 0, mu_id: int = 0, div: int = 0) -> Response:
div: int = 0) -> Response: return self.get(f"{self.url}/main/leaderboards-damage-rankings/{country_id}/{weeks}/{mu_id}/{div}")
data = (country, weeks, mu, div)
return self.get("{}/main/leaderboards-damage-rankings/{}/{}/{}/{}".format(self.url, *data))
def _get_main_leaderboards_kills_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response: def _get_main_leaderboards_kills_aircraft_rankings(self, country_id: int, weeks: int = 0, mu_id: int = 0) -> Response:
data = (country, weeks, mu) return self.get(f"{self.url}/main/leaderboards-kills-aircraft-rankings/{country_id}/{weeks}/{mu_id}/0")
return self.get("{}/main/leaderboards-kills-aircraft-rankings/{}/{}/{}/0".format(self.url, *data))
def _get_main_leaderboards_kills_rankings(self, country: int, weeks: int = 0, mu: int = 0, def _get_main_leaderboards_kills_rankings(self, country_id: int, weeks: int = 0, mu_id: int = 0, div: int = 0) -> Response:
div: int = 0) -> Response: return self.get(f"{self.url}/main/leaderboards-kills-rankings/{country_id}/{weeks}/{mu_id}/{div}")
data = (country, weeks, mu, div)
return self.get("{}/main/leaderboards-kills-rankings/{}/{}/{}/{}".format(self.url, *data))
class ErepublikLocationAPI(CitizenBaseAPI): class ErepublikLocationAPI(CitizenBaseAPI):
def _get_main_city_data_residents(self, city: int, page: int = 1, params: Mapping[str, Any] = None) -> Response: def _get_main_city_data_residents(self, city_id: int, page: int = 1, params: Mapping[str, Any] = None) -> Response:
if params is None: if params is None:
params = {} params = {}
return self.get("{}/main/city-data/{}/residents".format(self.url, city), params={"currentPage": page, **params}) return self.get(f"{self.url}/main/city-data/{city_id}/residents", params={"currentPage": page, **params})
class ErepublikMilitaryAPI(CitizenBaseAPI): class ErepublikMilitaryAPI(CitizenBaseAPI):
def _get_military_battlefield_choose_side(self, battle: int, side: int) -> Response: def _get_military_battlefield_choose_side(self, battle_id: int, side_id: int) -> Response:
return self.get("{}/military/battlefield-choose-side/{}/{}".format(self.url, battle, side)) return self.get(f"{self.url}/military/battlefield-choose-side/{battle_id}/{side_id}")
def _get_military_show_weapons(self, battle: int) -> Response: def _get_military_show_weapons(self, battle_id: int) -> Response:
return self.get("{}/military/show-weapons".format(self.url), params={'_token': self.token, 'battleId': battle}) return self.get(f"{self.url}/military/show-weapons", params={'_token': self.token, 'battleId': battle_id})
def _get_military_campaigns(self) -> Response: def _get_military_campaigns(self) -> Response:
return self.get("{}/military/campaigns-new/".format(self.url)) return self.get(f"{self.url}/military/campaigns-new/")
def _get_military_campaigns_json_list(self) -> Response: def _get_military_campaigns_json_list(self) -> Response:
return self.get("{}/military/campaignsJson/list".format(self.url)) return self.get(f"{self.url}/military/campaignsJson/list")
def _get_military_campaigns_json_citizen(self) -> Response: def _get_military_campaigns_json_citizen(self) -> Response:
return self.get("{}/military/campaignsJson/citizen".format(self.url)) return self.get(f"{self.url}/military/campaignsJson/citizen")
def _get_military_unit_data(self, unit_id: int, **kwargs) -> Response: def _get_military_unit_data(self, unit_id: int, **kwargs) -> Response:
params = {"groupId": unit_id, "panel": "members", **kwargs} params = {"groupId": unit_id, "panel": "members", **kwargs}
return self.get("{}/military/military-unit-data/".format(self.url), params=params) return self.get(f"{self.url}/military/military-unit-data/", params=params)
def _post_main_activate_battle_effect(self, battle: int, kind: str, citizen_id: int) -> Response: def _post_main_activate_battle_effect(self, battle_id: int, kind: str, citizen_id: int) -> Response:
data = dict(battleId=battle, citizenId=citizen_id, type=kind, _token=self.token) data = dict(battleId=battle_id, citizenId=citizen_id, type=kind, _token=self.token)
return self.post("{}/main/fight-activateBattleEffect".format(self.url), data=data) return self.post(f"{self.url}/main/fight-activateBattleEffect", data=data)
def _post_main_battlefield_travel(self, side_id: int, battle_id: int) -> Response: def _post_main_battlefield_travel(self, side_id: int, battle_id: int) -> Response:
data = dict(_token=self.token, sideCountryId=side_id, battleId=battle_id) data = dict(_token=self.token, sideCountryId=side_id, battleId=battle_id)
return self.post("{}/main/battlefieldTravel".format(self.url), data=data) return self.post(f"{self.url}/main/battlefieldTravel", data=data)
def _post_main_battlefield_change_division(self, battle_id: int, division_id: int) -> Response: def _post_main_battlefield_change_division(self, battle_id: int, division_id: int) -> Response:
data = dict(_token=self.token, battleZoneId=division_id, battleId=battle_id) data = dict(_token=self.token, battleZoneId=division_id, battleId=battle_id)
return self.post("{}/main/battlefieldTravel".format(self.url), data=data) return self.post(f"{self.url}/main/battlefieldTravel", data=data)
def _get_wars_show(self, war_id: int) -> Response: def _get_wars_show(self, war_id: int) -> Response:
return self.get("{}/wars/show/{}".format(self.url, war_id)) return self.get(f"{self.url}/wars/show/{war_id}")
def _post_military_fight_activate_booster(self, battle: int, quality: int, duration: int, kind: str) -> Response: def _post_military_fight_activate_booster(self, battle_id: int, quality: int, duration: int, kind: str) -> Response:
data = dict(type=kind, quality=quality, duration=duration, battleId=battle, _token=self.token) data = dict(type=kind, quality=quality, duration=duration, battleId=battle_id, _token=self.token)
return self.post("{}/military/fight-activateBooster".format(self.url), data=data) return self.post(f"{self.url}/military/fight-activateBooster", data=data)
def _post_military_change_weapon(self, battle: int, battle_zone: int, weapon_level: int, ) -> Response: def _post_military_change_weapon(self, battle_id: int, battle_zone: int, weapon_level: int, ) -> Response:
data = dict(battleId=battle, _token=self.token, battleZoneId=battle_zone, customizationLevel=weapon_level) data = dict(battleId=battle_id, _token=self.token, battleZoneId=battle_zone, customizationLevel=weapon_level)
return self.post("{}/military/change-weapon".format(self.url), data=data) return self.post(f"{self.url}/military/change-weapon", data=data)
def _post_military_battle_console(self, battle_id: int, action: str, page: int = 1, **kwargs) -> Response: def _post_military_battle_console(self, battle_id: int, action: str, page: int = 1, **kwargs) -> Response:
data = dict(battleId=battle_id, action=action, _token=self.token) data = dict(battleId=battle_id, action=action, _token=self.token)
@ -417,19 +415,19 @@ class ErepublikMilitaryAPI(CitizenBaseAPI):
division=kwargs["division"], type=kwargs.get("type", 'damage'), ) division=kwargs["division"], type=kwargs.get("type", 'damage'), )
elif action == "warList": elif action == "warList":
data.update(page=page) data.update(page=page)
return self.post("{}/military/battle-console".format(self.url), data=data) return self.post(f"{self.url}/military/battle-console", data=data)
def _post_military_deploy_bomb(self, battle_id: int, bomb_id: int) -> Response: def _post_military_deploy_bomb(self, battle_id: int, bomb_id: int) -> Response:
data = dict(battleId=battle_id, bombId=bomb_id, _token=self.token) data = dict(battleId=battle_id, bombId=bomb_id, _token=self.token)
return self.post("{}/military/deploy-bomb".format(self.url), data=data) return self.post(f"{self.url}/military/deploy-bomb", data=data)
def _post_military_fight_air(self, battle_id: int, side_id: int, zone_id: int) -> Response: def _post_military_fight_air(self, battle_id: int, side_id: int, zone_id: int) -> Response:
data = dict(sideId=side_id, battleId=battle_id, _token=self.token, battleZoneId=zone_id) data = dict(sideId=side_id, battleId=battle_id, _token=self.token, battleZoneId=zone_id)
return self.post("{}/military/fight-shoooot/{}".format(self.url, battle_id), data=data) return self.post(f"{self.url}/military/fight-shoooot/{battle_id}", data=data)
def _post_military_fight_ground(self, battle_id: int, side_id: int, zone_id: int) -> Response: def _post_military_fight_ground(self, battle_id: int, side_id: int, zone_id: int) -> Response:
data = dict(sideId=side_id, battleId=battle_id, _token=self.token, battleZoneId=zone_id) data = dict(sideId=side_id, battleId=battle_id, _token=self.token, battleZoneId=zone_id)
return self.post("{}/military/fight-shooot/{}".format(self.url, battle_id), data=data) return self.post(f"{self.url}/military/fight-shooot/{battle_id}", data=data)
def _post_fight_deploy_deploy_report_data(self, deployment_id: int): def _post_fight_deploy_deploy_report_data(self, deployment_id: int):
data = dict(_token=self.token, deploymentId=deployment_id) data = dict(_token=self.token, deploymentId=deployment_id)
@ -438,21 +436,28 @@ class ErepublikMilitaryAPI(CitizenBaseAPI):
class ErepublikPoliticsAPI(CitizenBaseAPI): class ErepublikPoliticsAPI(CitizenBaseAPI):
def _get_candidate_party(self, party_slug: str) -> Response: def _get_candidate_party(self, party_slug: str) -> Response:
return self.post("{}/candidate/{}".format(self.url, party_slug)) return self.get(f"{self.url}/candidate/{party_slug}")
def _get_main_party_members(self, party: int) -> Response: def _get_main_party_members(self, party_id: int) -> Response:
return self.get("{}/main/party-members/{}".format(self.url, party)) return self.get(f"{self.url}/main/party-members/{party_id}")
def _get_main_rankings_parties(self, country: int) -> Response: def _get_main_rankings_parties(self, country_id: int) -> Response:
return self.get("{}/main/rankings-parties/1/{}".format(self.url, country)) return self.get(f"{self.url}/main/rankings-parties/1/{country_id}")
def _post_candidate_for_congress(self, presentation: str = "") -> Response: def _post_candidate_for_congress(self, presentation: str = "") -> Response:
data = dict(_token=self.token, presentation=presentation) data = dict(_token=self.token, presentation=presentation)
return self.post("{}/candidate-for-congress".format(self.url), data=data) return self.post(f"{self.url}/candidate-for-congress", data=data)
def _get_presidential_elections(self, country_id: int, timestamp: int) -> Response: def _get_presidential_elections(self, country_id: int, timestamp: int) -> Response:
return self.get(f"{self.url}/main/presidential-elections/{country_id}/{timestamp}") return self.get(f"{self.url}/main/presidential-elections/{country_id}/{timestamp}")
def _post_propose_president_candidate(self, party_slug: str, citizen_id: int) -> Response:
return self.post(f"{self.url}/propose-president-candidate/{party_slug}",
data=dict(_token=self.token, citizen=citizen_id))
def _get_auto_propose_president_candidate(self, party_slug: str) -> Response:
return self.get(f"{self.url}/auto-propose-president-candidate/{party_slug}")
class ErepublikPresidentAPI(CitizenBaseAPI): class ErepublikPresidentAPI(CitizenBaseAPI):
def _post_wars_attack_region(self, war_id: int, region_id: int, region_name: str) -> Response: def _post_wars_attack_region(self, war_id: int, region_id: int, region_name: str) -> Response:
@ -462,50 +467,50 @@ class ErepublikPresidentAPI(CitizenBaseAPI):
def _post_new_war(self, self_country_id: int, attack_country_id: int, debate: str = "") -> Response: def _post_new_war(self, self_country_id: int, attack_country_id: int, debate: str = "") -> Response:
data = dict(requirments=1, _token=self.token, debate=debate, data = dict(requirments=1, _token=self.token, debate=debate,
countryNameConfirm=constants.COUNTRIES[attack_country_id].link) countryNameConfirm=constants.COUNTRIES[attack_country_id].link)
return self.post("{}/{}/new-war".format(self.url, constants.COUNTRIES[self_country_id].link), data=data) return self.post(f"{self.url}/{constants.COUNTRIES[self_country_id].link}/new-war", data=data)
def _post_new_donation(self, country_id: int, amount: int, org_name: str, debate: str = "") -> Response: def _post_new_donation(self, country_id: int, amount: int, org_name: str, debate: str = "") -> Response:
data = dict(requirments=1, _token=self.token, debate=debate, currency=1, value=amount, commit='Propose', data = dict(requirments=1, _token=self.token, debate=debate, currency=1, value=amount, commit='Propose',
type_name=org_name) type_name=org_name)
return self.post("{}/{}/new-donation".format(self.url, constants.COUNTRIES[country_id].link), data=data) return self.post(f"{self.url}/{constants.COUNTRIES[country_id].link}/new-donation", data=data)
class ErepublikProfileAPI(CitizenBaseAPI): class ErepublikProfileAPI(CitizenBaseAPI):
def _get_main_citizen_hovercard(self, citizen: int) -> Response: def _get_main_citizen_hovercard(self, citizen_id: int) -> Response:
return self.get("{}/main/citizen-hovercard/{}".format(self.url, citizen)) return self.get(f"{self.url}/main/citizen-hovercard/{citizen_id}")
def _get_main_citizen_profile_json(self, player_id: int) -> Response: def _get_main_citizen_profile_json(self, citizen_id: int) -> Response:
return self.get("{}/main/citizen-profile-json/{}".format(self.url, player_id)) return self.get(f"{self.url}/main/citizen-profile-json/{citizen_id}")
def _get_main_citizen_notifications(self) -> Response: def _get_main_citizen_notifications(self) -> Response:
return self.get("{}/main/citizenDailyAssistant".format(self.url)) return self.get(f"{self.url}/main/citizenDailyAssistant")
def _get_main_citizen_daily_assistant(self) -> Response: def _get_main_citizen_daily_assistant(self) -> Response:
return self.get("{}/main/citizenNotifications".format(self.url)) return self.get(f"{self.url}/main/citizenNotifications")
def _get_main_messages_paginated(self, page: int = 1) -> Response: def _get_main_messages_paginated(self, page: int = 1) -> Response:
return self.get("{}/main/messages-paginated/{}".format(self.url, page)) return self.get(f"{self.url}/main/messages-paginated/{page}")
def _get_main_money_donation_accept(self, donation_id: int) -> Response: def _get_main_money_donation_accept(self, donation_id: int) -> Response:
return self.get("{}/main/money-donation/accept/{}".format(self.url, donation_id), params={"_token": self.token}) return self.get(f"{self.url}/main/money-donation/accept/{donation_id}", params={"_token": self.token})
def _get_main_money_donation_reject(self, donation_id: int) -> Response: def _get_main_money_donation_reject(self, donation_id: int) -> Response:
return self.get("{}/main/money-donation/reject/{}".format(self.url, donation_id), params={"_token": self.token}) return self.get(f"{self.url}/main/money-donation/reject/{donation_id}", params={"_token": self.token})
def _get_main_notifications_ajax_community(self, page: int = 1) -> Response: def _get_main_notifications_ajax_community(self, page: int = 1) -> Response:
return self.get("{}/main/notificationsAjax/community/{}".format(self.url, page)) return self.get(f"{self.url}/main/notificationsAjax/community/{page}")
def _get_main_notifications_ajax_system(self, page: int = 1) -> Response: def _get_main_notifications_ajax_system(self, page: int = 1) -> Response:
return self.get("{}/main/notificationsAjax/system/{}".format(self.url, page)) return self.get(f"{self.url}/main/notificationsAjax/system/{page}")
def _get_main_notifications_ajax_report(self, page: int = 1) -> Response: def _get_main_notifications_ajax_report(self, page: int = 1) -> Response:
return self.get("{}/main/notificationsAjax/report/{}".format(self.url, page)) return self.get(f"{self.url}/main/notificationsAjax/report/{page}")
def _get_main_training_grounds_json(self) -> Response: def _get_main_training_grounds_json(self) -> Response:
return self.get("{}/main/training-grounds-json".format(self.url)) return self.get(f"{self.url}/main/training-grounds-json")
def _get_main_weekly_challenge_data(self) -> Response: def _get_main_weekly_challenge_data(self) -> Response:
return self.get("{}/main/weekly-challenge-data".format(self.url)) return self.get(f"{self.url}/main/weekly-challenge-data")
def _post_main_citizen_add_remove_friend(self, citizen: int, add: bool) -> Response: def _post_main_citizen_add_remove_friend(self, citizen: int, add: bool) -> Response:
data = dict(_token=self.token, citizenId=citizen, url="//www.erepublik.com/en/main/citizen-addRemoveFriend") data = dict(_token=self.token, citizenId=citizen, url="//www.erepublik.com/en/main/citizen-addRemoveFriend")
@ -513,60 +518,60 @@ class ErepublikProfileAPI(CitizenBaseAPI):
data.update({"action": "addFriend"}) data.update({"action": "addFriend"})
else: else:
data.update({"action": "removeFriend"}) data.update({"action": "removeFriend"})
return self.post("{}/main/citizen-addRemoveFriend".format(self.url), data=data) return self.post(f"{self.url}/main/citizen-addRemoveFriend", data=data)
def _post_main_daily_task_reward(self) -> Response: def _post_main_daily_task_reward(self) -> Response:
return self.post("{}/main/daily-tasks-reward".format(self.url), data=dict(_token=self.token)) return self.post(f"{self.url}/main/daily-tasks-reward", data=dict(_token=self.token))
def _post_delete_message(self, msg_id: list) -> Response: def _post_delete_message(self, msg_id: list) -> Response:
data = {"_token": self.token, "delete_message[]": msg_id} data = {"_token": self.token, "delete_message[]": msg_id}
return self.post("{}/main/messages-delete".format(self.url), data) return self.post(f"{self.url}/main/messages-delete", data)
def _post_eat(self, color: str) -> Response: def _post_eat(self, color: str) -> Response:
data = dict(_token=self.token, buttonColor=color) data = dict(_token=self.token, buttonColor=color)
return self.post("{}/main/eat".format(self.url), params=data) return self.post(f"{self.url}/main/eat", params=data)
def _post_main_global_alerts_close(self, alert_id: int) -> Response: def _post_main_global_alerts_close(self, alert_id: int) -> Response:
data = dict(_token=self.token, alert_id=alert_id) data = dict(_token=self.token, alert_id=alert_id)
return self.post("{}/main/global-alerts/close".format(self.url), data=data) return self.post(f"{self.url}/main/global-alerts/close", data=data)
def _post_forgot_password(self, email: str) -> Response: def _post_forgot_password(self, email: str) -> Response:
data = dict(_token=self.token, email=email, commit="Reset password") data = dict(_token=self.token, email=email, commit="Reset password")
return self.post("{}/forgot-password".format(self.url), data=data) return self.post(f"{self.url}/forgot-password", data=data)
def _post_login(self, email: str, password: str) -> Response: def _post_login(self, email: str, password: str) -> Response:
data = dict(csrf_token=self.token, citizen_email=email, citizen_password=password, remember='on') data = dict(csrf_token=self.token, citizen_email=email, citizen_password=password, remember='on')
return self.post("{}/login".format(self.url), data=data) return self.post(f"{self.url}/login", data=data)
def _post_main_messages_alert(self, notification_ids: List[int]) -> Response: def _post_main_messages_alert(self, notification_ids: List[int]) -> Response:
data = {"_token": self.token, "delete_alerts[]": notification_ids, "deleteAllAlerts": "1", "delete": "Delete"} data = {"_token": self.token, "delete_alerts[]": notification_ids, "deleteAllAlerts": "1", "delete": "Delete"}
return self.post("{}/main/messages-alerts/1".format(self.url), data=data) return self.post(f"{self.url}/main/messages-alerts/1", data=data)
def _post_main_notifications_ajax_community(self, notification_ids: List[int], page: int = 1) -> Response: def _post_main_notifications_ajax_community(self, notification_ids: List[int], page: int = 1) -> Response:
data = {"_token": self.token, "delete_alerts[]": notification_ids} data = {"_token": self.token, "delete_alerts[]": notification_ids}
return self.post("{}/main/notificationsAjax/community/{}".format(self.url, page), data=data) return self.post(f"{self.url}/main/notificationsAjax/community/{page}", data=data)
def _post_main_notifications_ajax_system(self, notification_ids: List[int], page: int = 1) -> Response: def _post_main_notifications_ajax_system(self, notification_ids: List[int], page: int = 1) -> Response:
data = {"_token": self.token, "delete_alerts[]": notification_ids} data = {"_token": self.token, "delete_alerts[]": notification_ids}
return self.post("{}/main/notificationsAjax/system/{}".format(self.url, page), data=data) return self.post(f"{self.url}/main/notificationsAjax/system/{page}", data=data)
def _post_main_notifications_ajax_report(self, notification_ids: List[int], page: int = 1) -> Response: def _post_main_notifications_ajax_report(self, notification_ids: List[int], page: int = 1) -> Response:
data = {"_token": self.token, "delete_alerts[]": notification_ids} data = {"_token": self.token, "delete_alerts[]": notification_ids}
return self.post("{}/main/notificationsAjax/report/{}".format(self.url, page), data=data) return self.post(f"{self.url}/main/notificationsAjax/report/{page}", data=data)
def _post_main_messages_compose(self, subject: str, body: str, citizens: List[int]) -> Response: def _post_main_messages_compose(self, subject: str, body: str, citizens: List[int]) -> Response:
url_pk = 0 if len(citizens) > 1 else str(citizens[0]) url_pk = 0 if len(citizens) > 1 else str(citizens[0])
data = dict(citizen_name=",".join([str(x) for x in citizens]), data = dict(citizen_name=",".join([str(x) for x in citizens]),
citizen_subject=subject, _token=self.token, citizen_message=body) citizen_subject=subject, _token=self.token, citizen_message=body)
return self.post("{}/main/messages-compose/{}".format(self.url, url_pk), data=data) return self.post(f"{self.url}/main/messages-compose/{url_pk}", data=data)
def _post_military_group_missions(self) -> Response: def _post_military_group_missions(self) -> Response:
data = dict(action="check", _token=self.token) data = dict(action="check", _token=self.token)
return self.post("{}/military/group-missions".format(self.url), data=data) return self.post(f"{self.url}/military/group-missions", data=data)
def _post_main_weekly_challenge_reward(self, reward_id: int) -> Response: def _post_main_weekly_challenge_reward(self, reward_id: int) -> Response:
data = dict(_token=self.token, rewardId=reward_id) data = dict(_token=self.token, rewardId=reward_id)
return self.post("{}/main/weekly-challenge-collect-reward".format(self.url), data=data) return self.post(f"{self.url}/main/weekly-challenge-collect-reward", data=data)
def _post_main_profile_update(self, action: str, params: str): def _post_main_profile_update(self, action: str, params: str):
data = {"action": action, "params": params, "_token": self.token} data = {"action": action, "params": params, "_token": self.token}
@ -576,10 +581,10 @@ class ErepublikProfileAPI(CitizenBaseAPI):
class ErepublikTravelAPI(CitizenBaseAPI): class ErepublikTravelAPI(CitizenBaseAPI):
def _post_main_travel(self, check: str, **kwargs) -> Response: def _post_main_travel(self, check: str, **kwargs) -> Response:
data = dict(_token=self.token, check=check, **kwargs) data = dict(_token=self.token, check=check, **kwargs)
return self.post("{}/main/travel".format(self.url), data=data) return self.post(f"{self.url}/main/travel", data=data)
def _post_main_travel_data(self, **kwargs) -> Response: def _post_main_travel_data(self, **kwargs) -> Response:
return self.post("{}/main/travelData".format(self.url), data=dict(_token=self.token, **kwargs)) return self.post(f"{self.url}/main/travelData", data=dict(_token=self.token, **kwargs))
class ErepublikWallPostAPI(CitizenBaseAPI): class ErepublikWallPostAPI(CitizenBaseAPI):
@ -587,78 +592,78 @@ class ErepublikWallPostAPI(CitizenBaseAPI):
def _post_main_country_comment_retrieve(self, post_id: int) -> Response: def _post_main_country_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id} data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/country-comment/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/country-comment/retrieve/json", data=data)
def _post_main_country_comment_create(self, post_id: int, comment_message: str) -> Response: def _post_main_country_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message} data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/country-comment/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/country-comment/create/json", data=data)
def _post_main_country_post_create(self, body: str, post_as: int) -> Response: def _post_main_country_post_create(self, body: str, post_as: int) -> Response:
data = {"_token": self.token, "post_message": body, "post_as": post_as} data = {"_token": self.token, "post_message": body, "post_as": post_as}
return self.post("{}/main/country-post/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/country-post/create/json", data=data)
def _post_main_country_post_retrieve(self) -> Response: def _post_main_country_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False} data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/country-post/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/country-post/retrieve/json", data=data)
# ## Military Unit # ## Military Unit
def _post_main_military_unit_comment_retrieve(self, post_id: int) -> Response: def _post_main_military_unit_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id} data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/military-unit-comment/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/military-unit-comment/retrieve/json", data=data)
def _post_main_military_unit_comment_create(self, post_id: int, comment_message: str) -> Response: def _post_main_military_unit_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message} data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/military-unit-comment/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/military-unit-comment/create/json", data=data)
def _post_main_military_unit_post_create(self, body: str, post_as: int) -> Response: def _post_main_military_unit_post_create(self, body: str, post_as: int) -> Response:
data = {"_token": self.token, "post_message": body, "post_as": post_as} data = {"_token": self.token, "post_message": body, "post_as": post_as}
return self.post("{}/main/military-unit-post/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/military-unit-post/create/json", data=data)
def _post_main_military_unit_post_retrieve(self) -> Response: def _post_main_military_unit_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False} data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/military-unit-post/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/military-unit-post/retrieve/json", data=data)
# ## Party # ## Party
def _post_main_party_comment_retrieve(self, post_id: int) -> Response: def _post_main_party_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id} data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/party-comment/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/party-comment/retrieve/json", data=data)
def _post_main_party_comment_create(self, post_id: int, comment_message: str) -> Response: def _post_main_party_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message} data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/party-comment/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/party-comment/create/json", data=data)
def _post_main_party_post_create(self, body: str) -> Response: def _post_main_party_post_create(self, body: str) -> Response:
data = {"_token": self.token, "post_message": body} data = {"_token": self.token, "post_message": body}
return self.post("{}/main/party-post/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/party-post/create/json", data=data)
def _post_main_party_post_retrieve(self) -> Response: def _post_main_party_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False} data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/party-post/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/party-post/retrieve/json", data=data)
# ## Friend's Wall # ## Friend's Wall
def _post_main_wall_comment_retrieve(self, post_id: int) -> Response: def _post_main_wall_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id} data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/wall-comment/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/wall-comment/retrieve/json", data=data)
def _post_main_wall_comment_create(self, post_id: int, comment_message: str) -> Response: def _post_main_wall_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message} data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/wall-comment/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/wall-comment/create/json", data=data)
def _post_main_wall_post_create(self, body: str) -> Response: def _post_main_wall_post_create(self, body: str) -> Response:
data = {"_token": self.token, "post_message": body} data = {"_token": self.token, "post_message": body}
return self.post("{}/main/wall-post/create/json".format(self.url), data=data) return self.post(f"{self.url}/main/wall-post/create/json", data=data)
def _post_main_wall_post_retrieve(self) -> Response: def _post_main_wall_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False} data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/wall-post/retrieve/json".format(self.url), data=data) return self.post(f"{self.url}/main/wall-post/retrieve/json", data=data)
# ## Medal posting # ## Medal posting
def _post_main_wall_post_automatic(self, message: str, achievement_id: int) -> Response: def _post_main_wall_post_automatic(self, message: str, achievement_id: int) -> Response:
return self.post("{}/main/wall-post/automatic".format(self.url), data=dict(_token=self.token, message=message, return self.post(f"{self.url}/main/wall-post/automatic", data=dict(_token=self.token, message=message,
achievementId=achievement_id)) achievementId=achievement_id))
class CitizenAPI( class CitizenAPI(

View File

@ -22,12 +22,13 @@ class BaseCitizen(access_points.CitizenAPI):
ot_points: int = 0 ot_points: int = 0
food: Dict[str, int] = {"q1": 0, "q2": 0, "q3": 0, "q4": 0, "q5": 0, "q6": 0, "q7": 0, "total": 0} food: Dict[str, int] = {"q1": 0, "q2": 0, "q3": 0, "q4": 0, "q5": 0, "q6": 0, "q7": 0, "total": 0}
eb_normal = 0 eb_normal: int = 0
eb_double = 0 eb_double: int = 0
eb_small = 0 eb_small: int = 0
division = 0 division: int = 0
maverick: bool = False
eday = 0 eday: int = 0
config: classes.Config = None config: classes.Config = None
energy: classes.Energy = None energy: classes.Energy = None
@ -40,12 +41,10 @@ class BaseCitizen(access_points.CitizenAPI):
r: Response = None r: Response = None
name: str = "Not logged in!" name: str = "Not logged in!"
logged_in: bool = False logged_in: bool = False
commit_id: str = ""
restricted_ip: bool = False restricted_ip: bool = False
def __init__(self, email: str = "", password: str = ""): def __init__(self, email: str = "", password: str = ""):
super().__init__() super().__init__()
self.commit_id = utils.COMMIT_ID
self.config = classes.Config() self.config = classes.Config()
self.energy = classes.Energy() self.energy = classes.Energy()
self.details = classes.Details() self.details = classes.Details()
@ -210,11 +209,12 @@ class BaseCitizen(access_points.CitizenAPI):
self.details.xp = citizen.get("currentExperiencePoints", 0) self.details.xp = citizen.get("currentExperiencePoints", 0)
self.details.daily_task_done = citizen.get("dailyTasksDone", False) self.details.daily_task_done = citizen.get("dailyTasksDone", False)
self.details.daily_task_reward = citizen.get("hasReward", False) self.details.daily_task_reward = citizen.get("hasReward", False)
self.maverick = citizen.get("canSwitchDivisions", False)
if citizen.get("dailyOrderDone", False) and not citizen.get("hasDailyOrderReward", False): if citizen.get("dailyOrderDone", False) and not citizen.get("hasDailyOrderReward", False):
self._post_military_group_missions() self._post_military_group_missions()
self.details.next_pp.sort() self.details.next_pp.sort()
for skill in citizen.get("mySkills", {}).values(): for skill in citizen.get("terrainSkills", {}).values():
self.details.mayhem_skills.update({int(skill["terrain_id"]): int(skill["skill_points"])}) self.details.mayhem_skills.update({int(skill["terrain_id"]): int(skill["skill_points"])})
if citizen.get('party', []): if citizen.get('party', []):
@ -380,9 +380,9 @@ class BaseCitizen(access_points.CitizenAPI):
def report_error(self, msg: str = "", is_warning: bool = False): def report_error(self, msg: str = "", is_warning: bool = False):
if is_warning: if is_warning:
utils.process_warning(msg, self.name, sys.exc_info(), self, self.commit_id) utils.process_warning(msg, self.name, sys.exc_info(), self)
else: else:
utils.process_error(msg, self.name, sys.exc_info(), self, self.commit_id, None) utils.process_error(msg, self.name, sys.exc_info(), self, None, None)
def sleep(self, seconds: int): def sleep(self, seconds: int):
if seconds < 0: if seconds < 0:
@ -393,7 +393,7 @@ class BaseCitizen(access_points.CitizenAPI):
sleep(seconds) sleep(seconds)
def to_json(self, indent: bool = False) -> str: def to_json(self, indent: bool = False) -> str:
return utils.json.dumps(self, cls=classes.MyJSONEncoder, indent=4 if indent else None, sort_keys=True) return utils.json.dumps(self, cls=classes.MyJSONEncoder, indent=4 if indent else None)
def get_countries_with_regions(self) -> Set[constants.Country]: def get_countries_with_regions(self) -> Set[constants.Country]:
r_json = self._post_main_travel_data().json() r_json = self._post_main_travel_data().json()
@ -695,6 +695,17 @@ class CitizenTravel(BaseCitizen):
self.details.current_region = region_id self.details.current_region = region_id
self.details.current_country = country self.details.current_country = country
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')):
self._update_citizen_location(country, region_id)
return True
else:
if "Travelling too fast." in r_json.get('message'):
self.sleep(1)
return self._travel(country, region_id)
return False
def get_country_travel_region(self, country: constants.Country) -> int: def get_country_travel_region(self, country: constants.Country) -> int:
regions = self.get_travel_regions(country=country) regions = self.get_travel_regions(country=country)
regs = [] regs = []
@ -711,12 +722,12 @@ class CitizenTravel(BaseCitizen):
self.update_citizen_info() self.update_citizen_info()
res_r = self.details.residence_region res_r = self.details.residence_region
if self.details.residence_country and res_r and not res_r == self.details.current_region: if self.details.residence_country and res_r and not res_r == self.details.current_region:
r_json = self._travel(self.details.residence_country, self.details.residence_region).json() if self._travel(self.details.residence_country, self.details.residence_region):
if r_json.get('message', '') == 'success': self._report_action("TRAVEL", "Traveled to residence")
self._update_citizen_location(self.details.residence_country, self.details.current_region)
self._report_action("TRAVEL", "Traveled to residence", response=r_json)
return True return True
return False else:
self._report_action("TRAVEL", "Unable to travel to residence!")
return False
return True return True
def travel_to_region(self, region_id: int) -> bool: def travel_to_region(self, region_id: int) -> bool:
@ -725,12 +736,14 @@ class CitizenTravel(BaseCitizen):
return True return True
else: else:
country = constants.COUNTRIES[data.get('preselectCountryId')] country = constants.COUNTRIES[data.get('preselectCountryId')]
r_json = self._travel(country, region_id).json()
if r_json.get('message', '') == 'success': if self._travel(country, region_id):
self._update_citizen_location(country, region_id) self._report_action("TRAVEL", "Traveled to region")
self._report_action("TRAVEL", "Traveled to region", response=r_json)
return True return True
return False else:
self._report_action("TRAVEL", "Unable to travel to region!")
return False
def travel_to_country(self, country: constants.Country) -> bool: 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()
@ -742,11 +755,13 @@ class CitizenTravel(BaseCitizen):
regs.append((region['id'], region['distanceInKm'])) regs.append((region['id'], region['distanceInKm']))
if regs: if regs:
region_id = min(regs, key=lambda _: int(_[1]))[0] region_id = min(regs, key=lambda _: int(_[1]))[0]
r_json = self._travel(country, region_id).json()
if r_json.get('message', '') == 'success': if self._travel(country, region_id):
self._update_citizen_location(country, region_id) self._report_action("TRAVEL", f"Traveled to {country.name}")
self._report_action("TRAVEL", f"Traveled to {country.name}", response=r_json)
return True return True
else:
self._report_action("TRAVEL", f"Unable to travel to {country.name}!")
return False return False
def travel_to_holding(self, holding: classes.Holding) -> bool: def travel_to_holding(self, holding: classes.Holding) -> bool:
@ -756,15 +771,36 @@ class CitizenTravel(BaseCitizen):
else: else:
country = constants.COUNTRIES[data.get('preselectCountryId')] country = constants.COUNTRIES[data.get('preselectCountryId')]
region_id = data.get('preselectRegionId') region_id = data.get('preselectRegionId')
r_json = self._travel(country, region_id).json()
if r_json.get('message', '') == 'success':
self._update_citizen_location(country, region_id)
self._report_action("TRAVEL", f"Traveled to holding {holding}", response=r_json)
return True
return False
def get_travel_regions(self, holding: classes.Holding = None, battle: classes.Battle = None, country: constants.Country = None if self._travel(country, region_id):
) -> Union[List[Any], Dict[str, Dict[str, Any]]]: self._report_action("TRAVEL", f"Traveled to {holding}")
return True
else:
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)
regs = []
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 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}")
return True
else:
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( return self._post_main_travel_data(
holdingId=holding.id if holding else 0, holdingId=holding.id if holding else 0,
battleId=battle.id if battle else 0, battleId=battle.id if battle else 0,
@ -797,23 +833,21 @@ class CitizenCompanies(BaseCitizen):
def work_as_manager_in_holding(self, holding: classes.Holding) -> Optional[Dict[str, Any]]: def work_as_manager_in_holding(self, holding: classes.Holding) -> Optional[Dict[str, Any]]:
return self._work_as_manager(holding) return self._work_as_manager(holding)
def _work_as_manager(self, wam_holding: classes.Holding = None) -> Optional[Dict[str, Any]]: def _work_as_manager(self, wam_holding: classes.Holding) -> Optional[Dict[str, Any]]:
if self.restricted_ip: if self.restricted_ip:
return None return None
self.update_companies() self.update_companies()
self.update_inventory() self.update_inventory()
data = {"action_type": "production"} data = {"action_type": "production"}
extra = {} extra = {}
wam_list = [] raw_factories = wam_holding.get_wam_companies(raw_factory=True)
if wam_holding: fin_factories = wam_holding.get_wam_companies(raw_factory=False)
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"] free_inventory = self.inventory["total"] - self.inventory["used"]
wam_list = raw_factories + fin_factories wam_list = raw_factories + fin_factories
wam_list = wam_list[:self.energy.food_fights] wam_list = wam_list[:self.energy.food_fights]
while wam_list and free_inventory < self.my_companies.get_needed_inventory_usage(wam_list): while wam_list and free_inventory < self.my_companies.get_needed_inventory_usage(wam_list):
wam_list.pop(-1) wam_list.pop(-1)
if wam_list: if wam_list:
data.update(extra) data.update(extra)
@ -855,11 +889,7 @@ class CitizenCompanies(BaseCitizen):
Storage={1000: 1, 2000: 2} <- Building_type 2 Storage={1000: 1, 2000: 2} <- Building_type 2
""" """
company_name = {1: "Food", 2: "Weapons", 4: "House", 23: "Aircraft", company_name = constants.INDUSTRIES[industry_id]
7: "FRM q1", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5",
12: "WRM q1", 13: "WRM q2", 14: "WRM q3", 15: "WRM q4", 16: "WRM q5",
18: "HRM q1", 19: "HRM q2", 20: "HRM q3", 21: "HRM q4", 22: "HRM q5",
24: "ARM q1", 25: "ARM q2", 26: "ARM q3", 27: "ARM q4", 28: "ARM q5", }[industry_id]
if building_type == 2: if building_type == 2:
company_name = "Storage" company_name = "Storage"
self.write_log(f'{company_name} created!') self.write_log(f'{company_name} created!')
@ -984,7 +1014,7 @@ class CitizenEconomy(CitizenTravel):
self.write_log(f"Trying to sell unsupported industry {industry}") self.write_log(f"Trying to sell unsupported industry {industry}")
data = { data = {
"country": self.details.citizenship, "country_id": self.details.citizenship.id,
"industry": industry, "industry": industry,
"quality": quality, "quality": quality,
"amount": amount, "amount": amount,
@ -1039,7 +1069,7 @@ class CitizenEconomy(CitizenTravel):
start_dt = self.now start_dt = self.now
iterable = [countries, [quality] if quality else range(1, max_quality + 1)] iterable = [countries, [quality] if quality else range(1, max_quality + 1)]
for country, q in product(*iterable): for country, q in product(*iterable):
r = self._post_economy_marketplace(country, constants.INDUSTRIES[product_name], q).json() r = self._post_economy_marketplace(country.id, constants.INDUSTRIES[product_name], q).json()
obj = offers[f"q{q}"] obj = offers[f"q{q}"]
if not r.get("error", False): if not r.get("error", False):
for offer in r["offers"]: for offer in r["offers"]:
@ -1165,9 +1195,9 @@ class CitizenEconomy(CitizenTravel):
if self.details.cc < amount or amount < 20: if self.details.cc < amount or amount < 20:
return False return False
data = dict(country=country.id, action='currency', value=amount) data = dict(country=country.id, action='currency', value=amount)
r = self._post_main_country_donate(**data) r = self._post_main_country_donate(country.id, 'currency', amount)
if r.json().get('status') or not r.json().get('error'): if r.json().get('status') or not r.json().get('error'):
self._report_action("CONTRIBUTE_CC", f'Contributed {amount}cc to {country}\'s treasury') self._report_action("CONTRIBUTE_CC", f'Contributed {amount}cc to {country}\'s treasury', kwargs=data)
return True return True
else: else:
self._report_action("CONTRIBUTE_CC", f"Unable to contribute {amount}cc to {country}'s" self._report_action("CONTRIBUTE_CC", f"Unable to contribute {amount}cc to {country}'s"
@ -1180,11 +1210,11 @@ class CitizenEconomy(CitizenTravel):
if self.food["q" + str(quality)] < amount or amount < 10: if self.food["q" + str(quality)] < amount or amount < 10:
return False return False
data = dict(country=country.id, action='food', value=amount, quality=quality) data = dict(country=country.id, action='food', value=amount, quality=quality)
r = self._post_main_country_donate(**data) r = self._post_main_country_donate(country.id, 'currency', amount, quality)
if r.json().get('status') or not r.json().get('error'): if r.json().get('status') or not r.json().get('error'):
self._report_action("CONTRIBUTE_FOOD", f"Contributed {amount}q{quality} food to " self._report_action("CONTRIBUTE_FOOD", f"Contributed {amount}q{quality} food to "
f"{country}'s treasury") f"{country}'s treasury", kwargs=data)
return True return True
else: else:
self._report_action("CONTRIBUTE_FOOD", f"Unable to contribute {amount}q{quality} food to " self._report_action("CONTRIBUTE_FOOD", f"Unable to contribute {amount}q{quality} food to "
@ -1197,11 +1227,10 @@ class CitizenEconomy(CitizenTravel):
if self.details.cc < amount: if self.details.cc < amount:
return False return False
data = dict(country=country.id, action='gold', value=amount) data = dict(country=country.id, action='gold', value=amount)
self.reporter.report_action("CONTRIBUTE_GOLD", data, str(amount)) r = self._post_main_country_donate(country.id, 'gold', amount)
r = self._post_main_country_donate(**data)
if r.json().get('status') or not r.json().get('error'): if r.json().get('status') or not r.json().get('error'):
self._report_action("CONTRIBUTE_GOLD", f"Contributed {amount}g to {country}'s treasury") self._report_action("CONTRIBUTE_GOLD", f"Contributed {amount}g to {country}'s treasury", kwargs=data)
return True return True
else: else:
self._report_action("CONTRIBUTE_GOLD", f"Unable to contribute {amount}g to {country}'s" self._report_action("CONTRIBUTE_GOLD", f"Unable to contribute {amount}g to {country}'s"
@ -1260,8 +1289,8 @@ class CitizenMedia(BaseCitizen):
4: "Political debates and analysis", 5: "Financial business", 4: "Political debates and analysis", 5: "Financial business",
6: "Social interactions and entertainment"} 6: "Social interactions and entertainment"}
if kind in kinds: if kind in kinds:
data = {'title': title, 'content': content, 'country': self.details.citizenship, 'kind': kind} data = {'title': title, 'content': content, 'country': self.details.citizenship.id, 'kind': kind}
resp = self._post_main_write_article(**data) resp = self._post_main_write_article(title, content, self.details.citizenship.id, kind)
try: try:
article_id = int(resp.history[1].url.split("/")[-3]) 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)
@ -1283,9 +1312,6 @@ class CitizenMilitary(CitizenTravel):
boosters: Dict[int, Dict[int, int]] = {100: {}, 50: {}} boosters: Dict[int, Dict[int, int]] = {100: {}, 50: {}}
def update_war_info(self): def update_war_info(self):
if not self.details.current_country:
self.update_citizen_info()
if self.__last_war_update_data and self.__last_war_update_data.get('last_updated', if self.__last_war_update_data and self.__last_war_update_data.get('last_updated',
0) + 30 > self.now.timestamp(): 0) + 30 > self.now.timestamp():
r_json = self.__last_war_update_data r_json = self.__last_war_update_data
@ -1310,7 +1336,10 @@ class CitizenMilitary(CitizenTravel):
all_battles = {} all_battles = {}
for battle_data in r_json.get("battles", {}).values(): for battle_data in r_json.get("battles", {}).values():
all_battles[battle_data.get('id')] = classes.Battle(battle_data) all_battles[battle_data.get('id')] = classes.Battle(battle_data)
old_all_battles = self.all_battles
self.all_battles = all_battles self.all_battles = all_battles
for battle in old_all_battles.values():
utils._clear_up_battle_memory(battle)
def get_battle_for_war(self, war_id: int) -> Optional[classes.Battle]: def get_battle_for_war(self, war_id: int) -> Optional[classes.Battle]:
self.update_war_info() self.update_war_info()
@ -1485,33 +1514,33 @@ class CitizenMilitary(CitizenTravel):
ret_battles = ret_battles + cs_battles + deployed_battles + other_battles ret_battles = ret_battles + cs_battles + deployed_battles + other_battles
return ret_battles return ret_battles
def get_cheap_tp_divisions(self) -> Optional[classes.BattleDivision]: def get_cheap_tp_divisions(self) -> Dict[str, List[Tuple[int, classes.BattleDivision]]]:
air_divs: List[Tuple[classes.BattleDivision, int]] = [] air_divs: List[Tuple[int, classes.BattleDivision]] = []
ground_divs: List[Tuple[classes.BattleDivision, int]] = [] ground_divs: List[Tuple[int, classes.BattleDivision]] = []
for battle in reversed(self.sorted_battles(True, True)): for battle in reversed(self.sorted_battles(True, True)):
for division in battle.div.values(): for division in battle.div.values():
if not division.terrain: is_start_ok = utils.good_timedelta(division.battle.start, timedelta(minutes=-1)) < self.now
if division.is_air: if not division.terrain and is_start_ok and not division.div_end:
medal = self.get_battle_round_data(division)[ if division.is_air and self.config.air:
self.details.citizenship == division.battle.defender.id] division_medals = self.get_battle_round_data(division)
if not medal and division.battle.start: medal = division_medals[self.details.citizenship == division.battle.is_defender.country]
return division if not medal:
air_divs.append((0, division))
else: else:
air_divs.append((division, medal.get('1').get('raw_value'))) air_divs.append((medal.get('1').get('raw_value'), division))
else: elif not division.is_air and self.config.ground:
medal = self.get_battle_round_data(division)[ if not division.div == self.division and not self.maverick:
self.details.citizenship == division.battle.defender.id] continue
if not medal and division.battle.start: division_medals = self.get_battle_round_data(division)
return division medal = division_medals[self.details.citizenship == division.battle.is_defender.country]
if not medal:
ground_divs.append((0, division))
else: else:
ground_divs.append((division, medal.get('1').get('raw_value'))) ground_divs.append((medal.get('1').get('raw_value'), division))
if self.config.air: air_divs.sort(key=lambda z: (z[0], z[1].battle.start))
return min(air_divs, key=lambda x: x[1])[0] ground_divs.sort(key=lambda z: (z[0], z[1].battle.start))
elif self.config.ground: return {'air': air_divs, 'ground': ground_divs}
return min(ground_divs, key=lambda x: x[1])[0]
else:
return
@property @property
def has_battle_contribution(self): def has_battle_contribution(self):
@ -1531,7 +1560,7 @@ class CitizenMilitary(CitizenTravel):
if self.config.air and div.is_air: if self.config.air and div.is_air:
battle_zone = div battle_zone = div
break break
elif self.config.ground and not div.is_air and div.div == self.division: elif self.config.ground and not div.is_air and (div.div == self.division or self.maverick):
battle_zone = div battle_zone = div
break break
else: else:
@ -1572,13 +1601,14 @@ class CitizenMilitary(CitizenTravel):
if not self.travel_to_battle(battle, countries_to_travel): if not self.travel_to_battle(battle, countries_to_travel):
break break
self.change_division(battle, battle_zone) if self.change_division(battle, battle_zone):
self.set_default_weapon(battle, battle_zone) self.set_default_weapon(battle, battle_zone)
self.fight(battle, battle_zone, side) self.fight(battle, battle_zone, side)
self.travel_to_residence() self.travel_to_residence()
break break
def fight(self, battle: classes.Battle, division: classes.BattleDivision, side: classes.BattleSide = None, count: int = None) -> int: def fight(self, battle: classes.Battle, division: classes.BattleDivision, side: classes.BattleSide = None,
count: int = None) -> int:
"""Fight in a battle. """Fight in a battle.
Will auto activate booster and travel if allowed to do it. Will auto activate booster and travel if allowed to do it.
@ -1607,6 +1637,8 @@ class CitizenMilitary(CitizenTravel):
if count is None: if count is None:
count = self.should_fight()[0] count = self.should_fight()[0]
self.write_log(f"Fighting in battle for {battle.region_name} on {side} side\n{battle}\n{str(division)}")
total_damage = 0 total_damage = 0
total_hits = 0 total_hits = 0
while ok_to_fight and error_count < 10 and count > 0: while ok_to_fight and error_count < 10 and count > 0:
@ -1622,7 +1654,10 @@ class CitizenMilitary(CitizenTravel):
self.write_log("Hits: {:>4} | Damage: {}".format(total_hits, total_damage)) self.write_log("Hits: {:>4} | Damage: {}".format(total_hits, total_damage))
ok_to_fight = False ok_to_fight = False
if total_damage: if total_damage:
self.reporter.report_action("FIGHT", dict(battle=battle, side=side, dmg=total_damage, self.reporter.report_action('FIGHT', dict(battle_id=battle.id, side=side, dmg=total_damage,
air=battle.has_air, hits=total_hits,
round=battle.zone_id))
self.reporter.report_action("FIGHT", dict(battle=str(battle), side=str(side), dmg=total_damage,
air=battle.has_air, hits=total_hits)) air=battle.has_air, hits=total_hits))
return error_count return error_count
@ -1647,6 +1682,9 @@ class CitizenMilitary(CitizenTravel):
pass pass
elif r_json.get("message") == "NOT_ENOUGH_WEAPONS": elif r_json.get("message") == "NOT_ENOUGH_WEAPONS":
self.set_default_weapon(battle, division) self.set_default_weapon(battle, division)
elif r_json.get("message") == "Cannot activate a zone with a non-native division":
self.write_log("Wrong division!!")
return 0, 10, 0
elif r_json.get("message") == "FIGHT_DISABLED": elif r_json.get("message") == "FIGHT_DISABLED":
self._post_main_profile_update('options', self._post_main_profile_update('options',
params='{"optionName":"enable_web_deploy","optionValue":"off"}') params='{"optionName":"enable_web_deploy","optionValue":"off"}')
@ -1714,7 +1752,7 @@ class CitizenMilitary(CitizenTravel):
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 return deployed_count
def change_division(self, battle: classes.Battle, division: classes.BattleDivision): def change_division(self, battle: classes.Battle, division: classes.BattleDivision) -> bool:
"""Change division. """Change division.
:param battle: Battle :param battle: Battle
@ -1723,8 +1761,13 @@ class CitizenMilitary(CitizenTravel):
:type division: BattleDivision :type division: BattleDivision
:return: :return:
""" """
self._post_main_battlefield_change_division(battle.id, division.id) resp = self._post_main_battlefield_change_division(battle.id, division.id)
self._report_action("MILITARY_DIV_SWITCH", f"Switched to d{division.div} in battle {battle.id}") if resp.json().get('error'):
self.write_log(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())
return True
def get_ground_hit_dmg_value(self, rang: int = None, strength: float = None, elite: bool = None, ne: bool = False, 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: booster_50: bool = False, booster_100: bool = False, tp: bool = True) -> Decimal:
@ -1746,7 +1789,7 @@ class CitizenMilitary(CitizenTravel):
if not rang or elite is None: if not rang or elite is None:
r = self._get_main_citizen_profile_json(self.details.citizen_id).json() r = self._get_main_citizen_profile_json(self.details.citizen_id).json()
if not rang: if not rang:
rang = r['military']['militaryData']['air']['rankNumber'] rang = r['military']['militaryData']['aircraft']['rankNumber']
if elite is None: if elite is None:
elite = r['citizenAttributes']['level'] > 100 elite = r['citizenAttributes']['level'] > 100
@ -1858,12 +1901,12 @@ class CitizenMilitary(CitizenTravel):
def get_battle_round_data(self, division: classes.BattleDivision) -> Tuple[Any, Any]: def get_battle_round_data(self, division: classes.BattleDivision) -> Tuple[Any, Any]:
battle = division.battle battle = division.battle
data = dict(zoneId=battle.zone_id, round_id=battle.zone_id, division=division.div, r = self._post_military_battle_console(battle.id, "battleStatistics", 1,
battleZoneId=division.id, type="damage") zoneId=battle.zone_id, round_id=battle.zone_id, division=division.div,
r = self._post_military_battle_console(battle.id, "battleStatistics", 1, **data) battleZoneId=division.id, type="damage")
r_json = r.json() r_json = r.json()
return (r_json.get(str(battle.invader.id)).get("fighterData"), return (r_json.get(str(battle.invader.id)).get("fighterData"),
r_json.get(str(battle.defender.id)).get("fighterData")) r_json.get(str(battle.is_defender.id)).get("fighterData"))
def schedule_attack(self, war_id: int, region_id: int, region_name: str, at_time: datetime): def schedule_attack(self, war_id: int, region_id: int, region_name: str, at_time: datetime):
if at_time: if at_time:
@ -1888,25 +1931,6 @@ class CitizenMilitary(CitizenTravel):
self._post_wars_attack_region(war_id, region_id, region_name) 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 travel_to_battle(self, battle: classes.Battle, allowed_countries: List[constants.Country]) -> bool:
data = self.get_travel_regions(battle=battle)
regs = []
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 regs:
reg = min(regs, key=lambda _: int(_[0]))
region_id = reg[1]
country = reg[2]
r = self._travel(country, region_id).json()
if r.get('message', '') == 'success':
self._update_citizen_location(country, region_id)
return True
return False
def get_country_mus(self, country: constants.Country) -> Dict[int, str]: def get_country_mus(self, country: constants.Country) -> Dict[int, str]:
ret = {} ret = {}
r = self._get_main_leaderboards_damage_rankings(country.id) r = self._get_main_leaderboards_damage_rankings(country.id)
@ -1937,12 +1961,18 @@ class CitizenMilitary(CitizenTravel):
mu_id = profile.get('military', {}).get('militaryUnit', {}).get('id', 0) mu_id = profile.get('military', {}).get('militaryUnit', {}).get('id', 0)
if mu_id: if mu_id:
name = profile.get('citizen', {}).get('name') name = profile.get('citizen', {}).get('name')
params = dict(currentPage=1, panel="members", sortBy="dailyOrdersCompleted", member = self._get_military_unit_data(mu_id, currentPage=1, panel="members", sortBy="dailyOrdersCompleted",
weekFilter=f"week{weeks_ago}", search=name) weekFilter=f"week{weeks_ago}", search=name).json()
member = self._get_military_unit_data(mu_id, **params).json()
return member.get('panelContents', {}).get('members', [{}])[0].get('dailyOrdersCompleted') return member.get('panelContents', {}).get('members', [{}])[0].get('dailyOrdersCompleted')
return 0 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
class CitizenPolitics(BaseCitizen): class CitizenPolitics(BaseCitizen):
def get_country_parties(self, country: constants.Country = None) -> dict: def get_country_parties(self, country: constants.Country = None) -> dict:
@ -2188,20 +2218,19 @@ class CitizenTasks(BaseCitizen):
self._report_action('ECONOMY_TG_CONTRACT', 'Bought TG Contract', kwargs=extra) self._report_action('ECONOMY_TG_CONTRACT', 'Bought TG Contract', kwargs=extra)
return ret return ret
def find_new_job(self) -> Response: def find_new_job(self) -> bool:
r = self._get_economy_job_market_json(self.details.current_country.id) 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=0, salary=10) data = dict(citizen_id=0, salary=10)
for posting in jobs: for posting in jobs:
salary = posting.get("salary") salary = posting.get("salary")
limit = posting.get("salaryLimit", 0) limit = posting.get("salaryLimit", 0)
citizen_id = posting.get("citizen").get("id") 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": citizen_id, "salary": salary}) data.update(citizen_id=citizen_id, salary=salary)
self._report_action("ECONOMY_APPLY_FOR_JOB", f"I'm working now for {str(data['citizen'])}", kwargs=r.json()) return self.apply_to_employer(data['citizen_id'], data['salary'])
return self._post_economy_job_market_apply(**data)
def apply_to_employer(self, employer_id: int, salary: float) -> bool: def apply_to_employer(self, employer_id: int, salary: float) -> bool:
data = dict(citizenId=employer_id, salary=salary) data = dict(citizenId=employer_id, salary=salary)
@ -2316,11 +2345,11 @@ class Citizen(CitizenAnniversary, CitizenCompanies, CitizenEconomy, CitizenLeade
self.reporter.report_action("NEW_MEDAL", info) self.reporter.report_action("NEW_MEDAL", info)
def set_debug(self, debug: bool): def set_debug(self, debug: bool):
self.debug = debug self.debug = bool(debug)
self._req.debug = debug self._req.debug = bool(debug)
def set_pin(self, pin: int): def set_pin(self, pin: int):
self.details.pin = pin self.details.pin = int(pin)
def update_all(self, force_update=False): def update_all(self, force_update=False):
# Do full update max every 5 min # Do full update max every 5 min
@ -2493,7 +2522,8 @@ class Citizen(CitizenAnniversary, CitizenCompanies, CitizenEconomy, CitizenLeade
else: else:
if not start_place == (self.details.current_country, self.details.current_region): if not start_place == (self.details.current_country, self.details.current_region):
self.travel_to_holding(holding) self.travel_to_holding(holding)
return self._wam(holding) self._wam(holding)
return
elif response.get("message") == "not_enough_health_food": elif response.get("message") == "not_enough_health_food":
self.buy_food() self.buy_food()
self._wam(holding) self._wam(holding)
@ -2509,7 +2539,7 @@ class Citizen(CitizenAnniversary, CitizenCompanies, CitizenEconomy, CitizenLeade
:rtype: bool :rtype: bool
""" """
if self.restricted_ip: if self.restricted_ip:
self._report_action("IP_BLACKLISTED", "Fighting is not allowed from restricted IP!") self._report_action("IP_BLACKLISTED", "Work as manager is not allowed from restricted IP!")
return False return False
self.update_citizen_info() self.update_citizen_info()
self.update_companies() self.update_companies()
@ -2526,6 +2556,10 @@ class Citizen(CitizenAnniversary, CitizenCompanies, CitizenEconomy, CitizenLeade
self.update_companies() self.update_companies()
for holding in regions.values(): for holding in regions.values():
raw_usage = holding.get_wam_raw_usage()
if (raw_usage['frm'] + raw_usage['wrm']) * 100 + self.inventory['used'] > self.inventory['total']:
self._report_action('WAM_UNAVAILABLE', 'Not enough storage!')
continue
self.travel_to_holding(holding) self.travel_to_holding(holding)
self._wam(holding) self._wam(holding)
self.update_companies() self.update_companies()

View File

@ -1,6 +1,7 @@
import datetime import datetime
import hashlib import hashlib
import threading import threading
import weakref
from decimal import Decimal from decimal import Decimal
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union
@ -27,9 +28,10 @@ class Holding:
id: int id: int
region: int region: int
companies: List["Company"] companies: List["Company"]
_citizen = weakref.ReferenceType
def __init__(self, _id: int, region: int, citizen): def __init__(self, _id: int, region: int, citizen):
self.citizen = citizen self._citizen = weakref.ref(citizen)
self.id: int = _id self.id: int = _id
self.region: int = region self.region: int = region
self.companies: List["Company"] = list() self.companies: List["Company"] = list()
@ -93,8 +95,13 @@ class Holding:
def as_dict(self): def as_dict(self):
return dict(name=str(self), id=self.id, region=self.region, companies=self.companies, wam_count=self.wam_count) return dict(name=str(self), id=self.id, region=self.region, companies=self.companies, wam_count=self.wam_count)
@property
def citizen(self):
return self._citizen()
class Company: class Company:
_holding: weakref.ReferenceType
holding: Holding holding: Holding
id: int id: int
quality: int quality: int
@ -113,7 +120,7 @@ class Company:
base_production: Decimal, wam_enabled: bool, can_wam: bool, cannot_wam_reason: str, industry: int, base_production: Decimal, wam_enabled: bool, can_wam: bool, cannot_wam_reason: str, industry: int,
already_worked: bool, preset_works: int already_worked: bool, preset_works: int
): ):
self.holding: Holding = holding self._holding = weakref.ref(holding)
self.id: int = _id self.id: int = _id
self.industry: int = industry self.industry: int = industry
self.quality: int = self._get_real_quality(quality) self.quality: int = self._get_real_quality(quality)
@ -211,6 +218,10 @@ class Company:
# noinspection PyProtectedMember # noinspection PyProtectedMember
return self.holding.citizen._post_economy_upgrade_company(self.id, level, self.holding.citizen.details.pin) return self.holding.citizen._post_economy_upgrade_company(self.id, level, self.holding.citizen.details.pin)
@property
def holding(self):
return self._holding()
class MyCompanies: class MyCompanies:
work_units: int = 0 work_units: int = 0
@ -218,13 +229,13 @@ class MyCompanies:
ff_lockdown: int = 0 ff_lockdown: int = 0
holdings: Dict[int, Holding] holdings: Dict[int, Holding]
companies: List[Company] companies: weakref.WeakSet
_citizen: weakref.ReferenceType
def __init__(self, citizen): def __init__(self, citizen):
from erepublik import Citizen self._citizen = weakref.ref(citizen)
self.citizen: Citizen = citizen
self.holdings: Dict[int, Holding] = dict() self.holdings: Dict[int, Holding] = dict()
self.companies: List[Company] = list() self.companies: weakref.WeakSet = weakref.WeakSet()
self.next_ot_time = utils.now() self.next_ot_time = utils.now()
def prepare_holdings(self, holdings: Dict[str, Dict[str, Any]]): def prepare_holdings(self, holdings: Dict[str, Dict[str, Any]]):
@ -233,8 +244,9 @@ class MyCompanies:
""" """
for holding in holdings.values(): for holding in holdings.values():
if holding.get('id') not in self.holdings: if holding.get('id') not in self.holdings:
self.holdings.update( self.holdings.update({
{int(holding.get('id')): Holding(holding['id'], holding['region_id'], self.citizen)}) int(holding.get('id')): Holding(holding['id'], holding['region_id'], self.citizen)
})
if not self.holdings.get(0): if not self.holdings.get(0):
self.holdings.update({0: Holding(0, 0, self.citizen)}) # unassigned self.holdings.update({0: Holding(0, 0, self.citizen)}) # unassigned
@ -258,7 +270,7 @@ class MyCompanies:
company_dict.get('can_work_as_manager'), company_dict.get('cannot_work_as_manager_reason'), 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') company_dict.get('industry_id'), company_dict.get('already_worked'), company_dict.get('preset_works')
) )
self.companies.append(company) self.companies.add(company)
holding.add_company(company) holding.add_company(company)
def get_employable_factories(self) -> Dict[int, int]: def get_employable_factories(self) -> Dict[int, int]:
@ -282,6 +294,8 @@ class MyCompanies:
def __clear_data(self): def __clear_data(self):
for holding in self.holdings.values(): for holding in self.holdings.values():
for company in holding.companies: # noqa
del company
holding.companies.clear() holding.companies.clear()
self.companies.clear() self.companies.clear()
@ -290,6 +304,10 @@ class MyCompanies:
return dict(name=str(self), work_units=self.work_units, next_ot_time=self.next_ot_time, return dict(name=str(self), work_units=self.work_units, next_ot_time=self.next_ot_time,
ff_lockdown=self.ff_lockdown, holdings=self.holdings, company_count=len(self.companies)) ff_lockdown=self.ff_lockdown, holdings=self.holdings, company_count=len(self.companies))
@property
def citizen(self):
return self._citizen()
class Config: class Config:
email = "" email = ""
@ -528,10 +546,13 @@ class Reporter:
queue=self.__to_update) queue=self.__to_update)
def __init__(self, citizen): def __init__(self, citizen):
self.citizen = citizen self._citizen = weakref.ref(citizen)
self._req = Session() self._req = Session()
self.url = "https://api.erep.lv" self.url = "https://api.erep.lv"
self._req.headers.update({"user-agent": "Bot reporter v2"}) self._req.headers.update({"user-agent": "eRepublik Script Reporter v3",
'erep-version': utils.__version__,
'erep-user-id': self.citizen_id,
'erep-user-name': self.citizen.name})
self.__to_update = [] self.__to_update = []
self.__registered: bool = False self.__registered: bool = False
@ -541,6 +562,10 @@ class Reporter:
self.register_account() self.register_account()
self.allowed = True self.allowed = True
@property
def citizen(self):
return self._citizen()
def __update_key(self): def __update_key(self):
self.key = hashlib.md5(bytes(f"{self.name}:{self.email}", encoding="UTF-8")).hexdigest() self.key = hashlib.md5(bytes(f"{self.name}:{self.email}", encoding="UTF-8")).hexdigest()
@ -548,8 +573,10 @@ class Reporter:
if self.__to_update: if self.__to_update:
for unreported_data in self.__to_update: for unreported_data in self.__to_update:
unreported_data.update(player_id=self.citizen_id, key=self.key) unreported_data.update(player_id=self.citizen_id, key=self.key)
unreported_data = utils.json.loads(utils.json.dumps(unreported_data, cls=MyJSONEncoder))
self._req.post("{}/bot/update".format(self.url), json=unreported_data) self._req.post("{}/bot/update".format(self.url), json=unreported_data)
self.__to_update.clear() self.__to_update.clear()
data = utils.json.loads(utils.json.dumps(data, cls=MyJSONEncoder))
r = self._req.post("{}/bot/update".format(self.url), json=data) r = self._req.post("{}/bot/update".format(self.url), json=data)
return r return r
@ -602,13 +629,13 @@ class Reporter:
except: # noqa except: # noqa
return [] return []
def fetch_tasks(self) -> Optional[Tuple[str, Tuple[Any]]]: def fetch_tasks(self) -> List[str, Tuple[Any]]:
try: try:
task_response = self._req.get(f'{self.url}/api/v1/command', task_response = self._req.get(f'{self.url}/api/v1/command',
params=dict(citizen=self.citizen_id, key=self.key)) params=dict(citizen=self.citizen_id, key=self.key))
return task_response.json().get('task_collection') return task_response.json().get('task_collection')
except: # noqa except: # noqa
return return []
class MyJSONEncoder(utils.json.JSONEncoder): class MyJSONEncoder(utils.json.JSONEncoder):
@ -643,28 +670,29 @@ class BattleSide:
deployed: List[constants.Country] deployed: List[constants.Country]
allies: List[constants.Country] allies: List[constants.Country]
battle: "Battle" battle: "Battle"
_battle: weakref.ReferenceType
country: constants.Country country: constants.Country
defender: bool is_defender: bool
def __init__(self, battle: "Battle", country: constants.Country, points: int, allies: List[constants.Country], def __init__(self, battle: "Battle", country: constants.Country, points: int, allies: List[constants.Country],
deployed: List[constants.Country], defender: bool): deployed: List[constants.Country], defender: bool):
self.battle = battle self._battle = weakref.ref(battle)
self.country = country self.country = country
self.points = points self.points = points
self.allies = allies self.allies = allies
self.deployed = deployed self.deployed = deployed
self.defender = defender self.is_defender = defender
@property @property
def id(self) -> int: def id(self) -> int:
return self.country.id return self.country.id
def __repr__(self): def __repr__(self):
side_text = "Defender" if self.defender else "Invader " side_text = "Defender" if self.is_defender else "Invader "
return f"<BattleSide: {side_text} {self.country.name}|{self.points:02d}p>" return f"<BattleSide: {side_text} {self.country.name}|{self.points:02d}p>"
def __str__(self): def __str__(self):
side_text = "Defender" if self.defender else "Invader " side_text = "Defender" if self.is_defender else "Invader "
return f"{side_text} {self.country.name} - {self.points:02d} points" return f"{side_text} {self.country.name} - {self.points:02d} points"
def __format__(self, format_spec): def __format__(self, format_spec):
@ -672,8 +700,12 @@ class BattleSide:
@property @property
def as_dict(self): def as_dict(self):
return dict(points=self.points, country=self.country, defender=self.defender, allies=self.allies, return dict(points=self.points, country=self.country, is_defender=self.is_defender, allies=self.allies,
deployed=self.deployed, battle=repr(self.battle)) deployed=self.deployed)
@property
def battle(self):
return self._battle()
class BattleDivision: class BattleDivision:
@ -687,11 +719,12 @@ class BattleDivision:
terrain: int terrain: int
div: int div: int
battle: "Battle" battle: "Battle"
_battle: weakref.ReferenceType
@property @property
def as_dict(self): def as_dict(self):
return dict(id=self.id, division=self.div, terrain=(self.terrain, self.terrain_display), wall=self.wall, return dict(id=self.id, division=self.div, terrain=(self.terrain, self.terrain_display), wall=self.wall,
epic=self.epic, battle=str(self.battle), end=self.div_end) epic=self.epic, end=self.div_end)
@property @property
def is_air(self): def is_air(self):
@ -713,7 +746,7 @@ class BattleDivision:
:type wall_for: int :type wall_for: int
:type wall_dom: float :type wall_dom: float
""" """
self.battle = battle self._battle = weakref.ref(battle)
self.id = div_id self.id = div_id
self.end = end self.end = end
self.epic = epic self.epic = epic
@ -736,6 +769,10 @@ class BattleDivision:
def __repr__(self): def __repr__(self):
return f"<BattleDivision #{self.id} (battle #{self.battle.id})>" return f"<BattleDivision #{self.id} (battle #{self.battle.id})>"
@property
def battle(self):
return self._battle()
class Battle: class Battle:
id: int id: int
@ -754,7 +791,7 @@ class Battle:
def as_dict(self): 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, 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}, dict_lib=self.is_dict_lib, start=self.start, sides={'inv': self.invader, 'def': self.defender},
region=[self.region_id, self.region_name]) region=[self.region_id, self.region_name], link=self.link)
@property @property
def has_air(self) -> bool: def has_air(self) -> bool:
@ -763,6 +800,10 @@ class Battle:
return True return True
return not bool(self.zone_id % 4) return not bool(self.zone_id % 4)
@property
def has_started(self) -> bool:
return self.start <= utils.now()
@property @property
def has_ground(self) -> bool: def has_ground(self) -> bool:
for div in self.div.values(): for div in self.div.values():
@ -886,7 +927,7 @@ class TelegramBot:
def as_dict(self): def as_dict(self):
return {'chat_id': self.chat_id, 'api_url': self.api_url, 'player': self.player_name, 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, 'last_time': self._last_time, 'next_time': self._next_time, 'queue': self.__queue,
'initialized': self.__initialized, 'has_threads': bool(len(self._threads))} 'initialized': self.__initialized, 'has_threads': not self._threads}
def do_init(self, chat_id: int, token: str, player_name: str = ""): def do_init(self, chat_id: int, token: str, player_name: str = ""):
self.chat_id = chat_id self.chat_id = chat_id

View File

@ -19,6 +19,9 @@ class Country:
self.link = link self.link = link
self.iso = iso self.iso = iso
def __hash__(self):
return hash((self.id, self.name))
def __repr__(self): def __repr__(self):
return f"Country({self.id}, '{self.name}', '{self.link}', '{self.iso}')" return f"Country({self.id}, '{self.name}', '{self.link}', '{self.iso}')"
@ -46,16 +49,18 @@ class Country:
class Industries: class Industries:
__by_name = {'food': 1, 'weapons': 2, 'house': 4, 'aircraft': 23, __by_name = {'food': 1, 'weapon': 2, 'house': 4, 'aircraft': 23,
'foodraw': 7, 'weaponraw': 12, 'houseraw': 18, 'aircraftraw': 24,
'frm': 7, 'wrm': 12, 'hrm': 18, 'arm': 24,
'frm q1': 7, 'frm q2': 8, 'frm q3': 9, 'frm q4': 10, 'frm q5': 11, '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, '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, '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} 'arm q1': 24, 'arm q2': 25, 'arm q3': 26, 'arm q4': 27, 'arm q5': 28}
__by_id = {1: "Food", 2: "Weapons", 4: "House", 23: "Aircraft", __by_id = {1: "Food", 2: "Weapon", 4: "House", 23: "Aircraft",
7: "FRM q1", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5", 7: "foodRaw", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5",
12: "WRM q1", 13: "WRM q2", 14: "WRM q3", 15: "WRM q4", 16: "WRM q5", 12: "weaponRaw", 13: "WRM q2", 14: "WRM q3", 15: "WRM q4", 16: "WRM q5",
18: "HRM q1", 19: "HRM q2", 20: "HRM q3", 21: "HRM q4", 22: "HRM q5", 18: "houseRaw", 19: "HRM q2", 20: "HRM q3", 21: "HRM q4", 22: "HRM q5",
24: "ARM q1", 25: "ARM q2", 26: "ARM q3", 27: "ARM q4", 28: "ARM q5"} 24: "aircraftRaw", 25: "ARM q2", 26: "ARM q3", 27: "ARM q4", 28: "ARM q5"}
def __getitem__(self, item) -> Optional[Union[int, str]]: def __getitem__(self, item) -> Optional[Union[int, str]]:
if isinstance(item, int): if isinstance(item, int):
@ -108,7 +113,7 @@ COUNTRIES: Dict[int, Country] = {
44: Country(44, 'Greece', 'Greece', 'GRC'), 45: Country(45, 'Japan', 'Japan', 'JPN'), 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'), 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'), 49: Country(49, 'Indonesia', 'Indonesia', 'IDN'), 50: Country(50, 'Australia', 'Australia', 'AUS'),
51: Country(51, 'South Africa', 'South Africa', 'ZAF'), 51: Country(51, 'South Africa', 'South-Africa', 'ZAF'),
52: Country(52, 'Republic of Moldova', 'Republic-of-Moldova', 'MDA'), 52: Country(52, 'Republic of Moldova', 'Republic-of-Moldova', 'MDA'),
53: Country(53, 'Portugal', 'Portugal', 'PRT'), 54: Country(54, 'Ireland', 'Ireland', 'IRL'), 53: Country(53, 'Portugal', 'Portugal', 'PRT'), 54: Country(54, 'Ireland', 'Ireland', 'IRL'),
55: Country(55, 'Denmark', 'Denmark', 'DNK'), 56: Country(56, 'Iran', 'Iran', 'IRN'), 55: Country(55, 'Denmark', 'Denmark', 'DNK'), 56: Country(56, 'Iran', 'Iran', 'IRN'),

View File

@ -9,18 +9,18 @@ import traceback
import unicodedata import unicodedata
from decimal import Decimal from decimal import Decimal
from pathlib import Path from pathlib import Path
from typing import Any, List, Mapping, Optional, Union from typing import Any, List, Optional, Union, Dict
import requests import requests
from . import __commit_id__, __version__, constants from . import __version__, constants
try: try:
import simplejson as json import simplejson as json
except ImportError: except ImportError:
import json import json
__all__ = ['COMMIT_ID', 'VERSION', 'calculate_hit', 'caught_error', 'date_from_eday', 'eday_from_date', __all__ = ['VERSION', 'calculate_hit', 'caught_error', 'date_from_eday', 'eday_from_date',
'get_air_hit_dmg_value', 'get_file', 'get_ground_hit_dmg_value', 'get_sleep_seconds', 'good_timedelta', 'get_air_hit_dmg_value', 'get_file', 'get_ground_hit_dmg_value', 'get_sleep_seconds', 'good_timedelta',
'interactive_sleep', 'json', 'localize_dt', 'localize_timestamp', 'normalize_html_json', 'now', 'interactive_sleep', 'json', 'localize_dt', 'localize_timestamp', 'normalize_html_json', 'now',
'process_error', 'process_warning', 'send_email', 'silent_sleep', 'slugify', 'write_file', 'process_error', 'process_warning', 'send_email', 'silent_sleep', 'slugify', 'write_file',
@ -30,7 +30,6 @@ if not sys.version_info >= (3, 7):
raise AssertionError('This script requires Python version 3.7 and higher\n' raise AssertionError('This script requires Python version 3.7 and higher\n'
'But Your version is v{}.{}.{}'.format(*sys.version_info)) 'But Your version is v{}.{}.{}'.format(*sys.version_info))
COMMIT_ID: str = __commit_id__
VERSION: str = __version__ VERSION: str = __version__
@ -43,12 +42,11 @@ def localize_timestamp(timestamp: int) -> datetime.datetime:
def localize_dt(dt: Union[datetime.date, datetime.datetime]) -> datetime.datetime: def localize_dt(dt: Union[datetime.date, datetime.datetime]) -> datetime.datetime:
try: if isinstance(dt, datetime.datetime):
try: return constants.erep_tz.localize(dt)
return constants.erep_tz.localize(dt) elif isinstance(dt, datetime.date):
except AttributeError: return constants.erep_tz.localize(datetime.datetime.combine(dt, datetime.time(0, 0, 0)))
return constants.erep_tz.localize(datetime.datetime.combine(dt, datetime.time(0, 0, 0))) else:
except ValueError:
return dt.astimezone(constants.erep_tz) return dt.astimezone(constants.erep_tz)
@ -117,10 +115,12 @@ def _write_log(msg, timestamp: bool = True, should_print: bool = False):
def write_interactive_log(*args, **kwargs): def write_interactive_log(*args, **kwargs):
kwargs.pop("should_print", None)
_write_log(should_print=True, *args, **kwargs) _write_log(should_print=True, *args, **kwargs)
def write_silent_log(*args, **kwargs): def write_silent_log(*args, **kwargs):
kwargs.pop("should_print", None)
_write_log(should_print=False, *args, **kwargs) _write_log(should_print=False, *args, **kwargs)
@ -178,14 +178,14 @@ def write_request(response: requests.Response, is_error: bool = False):
"mimetype": "application/json" if ext == "json" else "text/html"} "mimetype": "application/json" if ext == "json" else "text/html"}
def send_email(name: str, content: List[Any], player=None, local_vars: Mapping[Any, Any] = None, def send_email(name: str, content: List[Any], player=None, local_vars: Dict[str, Any] = None,
promo: bool = False, captcha: bool = False): promo: bool = False, captcha: bool = False):
if local_vars is None: if local_vars is None:
local_vars = {} local_vars = {}
from erepublik import Citizen from erepublik import Citizen
file_content_template = "<html><head><title>{title}</title></head><body>{body}</body></html>" file_content_template = "<html><head><title>{title}</title></head><body>{body}</body></html>"
if isinstance(player, Citizen): if isinstance(player, Citizen) and player.r:
resp = write_request(player.r, is_error=True) resp = write_request(player.r, is_error=True)
else: else:
resp = {"name": "None.html", "mimetype": "text/html", resp = {"name": "None.html", "mimetype": "text/html",
@ -221,8 +221,16 @@ def send_email(name: str, content: List[Any], player=None, local_vars: Mapping[A
if local_vars: if local_vars:
if "state_thread" in local_vars: if "state_thread" in local_vars:
local_vars.pop('state_thread', None) local_vars.pop('state_thread', None)
if isinstance(local_vars.get('self'), Citizen):
local_vars['self'] = repr(local_vars['self'])
if isinstance(local_vars.get('player'), Citizen):
local_vars['player'] = repr(local_vars['player'])
if isinstance(local_vars.get('citizen'), Citizen):
local_vars['citizen'] = repr(local_vars['citizen'])
from erepublik.classes import MyJSONEncoder from erepublik.classes import MyJSONEncoder
files.append(('file', ("local_vars.json", json.dumps(local_vars, cls=MyJSONEncoder, sort_keys=True), files.append(('file', ("local_vars.json", json.dumps(local_vars, cls=MyJSONEncoder),
"application/json"))) "application/json")))
if isinstance(player, Citizen): if isinstance(player, Citizen):
files.append(('file', ("instance.json", player.to_json(indent=True), "application/json"))) files.append(('file', ("instance.json", player.to_json(indent=True), "application/json")))
@ -238,7 +246,7 @@ def normalize_html_json(js: str) -> str:
def caught_error(e: Exception): def caught_error(e: Exception):
process_error(str(e), "Unclassified", sys.exc_info(), None, COMMIT_ID, False) process_error(str(e), "Unclassified", sys.exc_info(), interactive=False)
def process_error(log_info: str, name: str, exc_info: tuple, citizen=None, commit_id: str = None, def process_error(log_info: str, name: str, exc_info: tuple, citizen=None, commit_id: str = None,
@ -260,7 +268,7 @@ def process_error(log_info: str, name: str, exc_info: tuple, citizen=None, commi
""" """
type_, value_, traceback_ = exc_info type_, value_, traceback_ = exc_info
content = [log_info] content = [log_info]
content += [f"eRepublik version {VERSION}, commit id {COMMIT_ID}"] content += [f"eRepublik version {VERSION}"]
if commit_id: if commit_id:
content += [f"Commit id {commit_id}"] content += [f"Commit id {commit_id}"]
content += [str(value_), str(type_), ''.join(traceback.format_tb(traceback_))] content += [str(value_), str(type_), ''.join(traceback.format_tb(traceback_))]
@ -270,16 +278,17 @@ def process_error(log_info: str, name: str, exc_info: tuple, citizen=None, commi
elif interactive is not None: elif interactive is not None:
write_silent_log(log_info) write_silent_log(log_info)
trace = inspect.trace() trace = inspect.trace()
local_vars = None
if trace: if trace:
trace = trace[-1][0].f_locals trace_local_vars = trace[-1][0].f_locals
if trace.get('__name__') == '__main__': if trace_local_vars.get('__name__') == '__main__':
trace = {'commit_id': trace.get('COMMIT_ID'), local_vars = {'commit_id': trace_local_vars.get('COMMIT_ID'),
'interactive': trace.get('INTERACTIVE'), 'interactive': trace_local_vars.get('INTERACTIVE'),
'version': trace.get('__version__'), 'version': trace_local_vars.get('__version__'),
'config': trace.get('CONFIG')} 'config': trace_local_vars.get('CONFIG')}
else: else:
trace = dict() local_vars = dict()
send_email(name, content, citizen, local_vars=trace) send_email(name, content, citizen, local_vars=local_vars)
def process_warning(log_info: str, name: str, exc_info: tuple, citizen=None, commit_id: str = None): def process_warning(log_info: str, name: str, exc_info: tuple, citizen=None, commit_id: str = None):
@ -299,10 +308,10 @@ def process_warning(log_info: str, name: str, exc_info: tuple, citizen=None, com
trace = inspect.trace() trace = inspect.trace()
if trace: if trace:
trace = trace[-1][0].f_locals local_vars = trace[-1][0].f_locals
else: else:
trace = dict() local_vars = dict()
send_email(name, content, citizen, local_vars=trace) send_email(name, content, citizen, local_vars=local_vars)
def slugify(value, allow_unicode=False) -> str: def slugify(value, allow_unicode=False) -> str:
@ -360,3 +369,9 @@ def get_air_hit_dmg_value(citizen_id: int, natural_enemy: bool = False, true_pat
rang = r['military']['militaryData']['aircraft']['rankNumber'] rang = r['military']['militaryData']['aircraft']['rankNumber']
elite = r['citizenAttributes']['level'] > 100 elite = r['citizenAttributes']['level'] > 100
return calculate_hit(0, rang, true_patriot, elite, natural_enemy, booster, weapon_power) return calculate_hit(0, rang, true_patriot, elite, natural_enemy, booster, weapon_power)
def _clear_up_battle_memory(battle):
del battle.invader._battle, battle.defender._battle
for div_id, division in battle.div.items():
del division._battle

View File

@ -1,17 +1,18 @@
bump2version==1.0.0 bump2version==1.0.0
coverage==5.1 coverage==5.3
edx-sphinx-theme==1.5.0 edx-sphinx-theme==1.5.0
flake8==3.8.3 flake8==3.8.3
ipython==7.15.0 ipython==7.18.1
isort==4.3.21 isort==5.5.3
pip==20.1.1 pip==20.2.3
PyInstaller==3.6 PyInstaller==4.0
pytz==2020.1 pytz==2020.1
requests==2.23.0 pytest==6.0.2
responses==0.10.15 responses==0.12.0
setuptools==47.1.1 setuptools==50.3.0
Sphinx==3.1.1 Sphinx==3.2.1
tox==3.15.2 requests==2.24.0
twine==3.1.1 tox==3.20.0
watchdog==0.10.2 twine==3.2.0
wheel==0.34.2 watchdog==0.10.3
wheel==0.35.1

View File

@ -1,5 +0,0 @@
#!/bin/bash
commit=$(git log -1 --pretty=format:%h)
sed -i.bak -E "s|__commit_id__ = \".+\"|__commit_id__ = \"${commit}\"|g" erepublik/__init__.py
rm erepublik/__init__.py.bak

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 0.20.3.6 current_version = 0.21.4
commit = True commit = True
tag = True tag = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.?(?P<dev>\d+)? parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.?(?P<dev>\d+)?
@ -33,7 +33,6 @@ ignore_missing_imports = False
warn_unused_ignores = True warn_unused_ignores = True
warn_redundant_casts = True warn_redundant_casts = True
warn_unused_configs = True warn_unused_configs = True
plugins = mypy_django_plugin.main
[isort] [isort]
multi_line_output = 2 multi_line_output = 2

View File

@ -11,7 +11,7 @@ with open('README.rst') as readme_file:
with open('HISTORY.rst') as history_file: with open('HISTORY.rst') as history_file:
history = history_file.read() history = history_file.read()
requirements = ['pytz==2020.1', 'requests==2.23.0'] requirements = ['pytz==2020.1', 'requests==2.24.0']
setup_requirements = [] setup_requirements = []
@ -43,6 +43,6 @@ setup(
test_suite='tests', test_suite='tests',
tests_require=test_requirements, tests_require=test_requirements,
url='https://github.com/eeriks/erepublik/', url='https://github.com/eeriks/erepublik/',
version='0.20.3.6', version='0.21.4',
zip_safe=False, zip_safe=False,
) )