Compare commits

...

32 Commits

Author SHA1 Message Date
e14cbc18e9 Bump version: 0.15.1 → 0.15.2 2019-08-01 17:24:07 +03:00
048ce798dd All battle div div containing dicts where reference to the same object 2019-08-01 17:23:24 +03:00
e5b7cde044 Bump version: 0.15.0 → 0.15.1 2019-08-01 15:06:34 +03:00
6bbc7a1f64 Typehinting and battle/war stuff - last battle, attackable regions if CP, etc 2019-08-01 15:05:44 +03:00
4eccb339bb Deploy bombs 2019-08-01 15:04:16 +03:00
dbeb6e9ba5 Market scraper updates 2019-08-01 09:37:26 +03:00
9c9bb5ae40 Region attacking post updated 2019-08-01 09:37:08 +03:00
d8eb69f82a Travel bugfix and market scraper fixup 2019-07-31 22:39:54 +03:00
42c430213f Minor updates 2019-07-31 21:41:24 +03:00
39dbcaa27d Continuing work on return Response free Citizen class 2019-07-31 21:41:08 +03:00
8911adb81c Traveling improved for Citizen class 2019-07-31 21:38:34 +03:00
7927c162f8 More precise type hint 2019-07-31 21:37:29 +03:00
92b7c45a7d Report promos to erep.lv 2019-07-31 21:36:57 +03:00
53257487d8 Write on country wall update 2019-07-30 18:32:12 +03:00
8690c4d3f2 minor fix 2019-07-30 11:10:35 +03:00
43c6bce160 minor fix 2019-07-30 11:10:09 +03:00
c4f598c1ba Bump version: 0.14.7 → 0.15.0 2019-07-30 10:22:38 +03:00
c48d90dec3 First step towards removing manual response parsing in Citizen class 2019-07-30 10:22:29 +03:00
953902476f Bump version: 0.14.6.1 → 0.14.7 2019-07-30 09:32:10 +03:00
156cbbb61c Typehinting changes 2019-07-30 09:32:03 +03:00
b72039c865 PyPi needs new version number, even if accidentaly published version has been removed 2019-07-29 15:17:14 +03:00
9587538fdc Merge branch 'master' of github.com:eeriks/erepublik_script
* 'master' of github.com:eeriks/erepublik_script:
  Bump version: 0.14.5 → 0.14.6
2019-07-29 13:54:09 +03:00
e775679581 Bump version: 0.14.5 → 0.14.6 2019-07-29 13:53:17 +03:00
3aa305ea74 Switch from python-slugify to self hosted (Taken from Django 2.2.1 django.utils.text.slugify) 2019-07-29 13:52:33 +03:00
6b2e5ffb68 Bump version: 0.14.5 → 0.14.6 2019-07-29 13:33:02 +03:00
bb8634fe56 After deleting debug directory next request failed if SlowRequests.debug == True 2019-07-29 13:31:07 +03:00
25a0d8993e eRepublikAPI now has it's own token property 2019-07-29 13:19:19 +03:00
a1d10bb427 Bump version: 0.14.4 → 0.14.5 2019-07-23 17:55:08 +03:00
ec701396d9 project name migration 2019-07-23 17:55:04 +03:00
d8035b42e3 Underline too short 2019-07-23 17:53:00 +03:00
42320a14a4 no message 2019-07-23 17:50:14 +03:00
de4b059b7d Package name update: erepublik_script → eRepublik 2019-07-23 16:41:21 +03:00
17 changed files with 657 additions and 486 deletions

View File

@ -57,7 +57,7 @@ If you are proposing a feature:
Get Started!
------------
Ready to contribute? Here's how to set up `erepublik_script` for local development.
Ready to contribute? Here's how to set up `erepublik` for local development.
1. Fork the `erepublik_script` repo on GitHub.
2. Clone your fork locally::
@ -66,8 +66,8 @@ Ready to contribute? Here's how to set up `erepublik_script` for local developme
3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development::
$ mkvirtualenv erepublik_script
$ cd erepublik_script/
$ mkvirtualenv erepublik
$ cd erepublik/
$ python setup.py develop
4. Create a branch for local development::
@ -79,7 +79,7 @@ Ready to contribute? Here's how to set up `erepublik_script` for local developme
5. When you're done making changes, check that your changes pass flake8 and the
tests, including testing other Python versions with tox::
$ flake8 erepublik_script tests
$ flake8 erepublik tests
$ python setup.py test or py.test
$ tox
@ -102,7 +102,7 @@ Before you submit a pull request, check that it meets these guidelines:
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.rst.
3. The pull request should work for Python 2.7, 3.4, 3.5 and 3.6, and for PyPy. Check
3. The pull request should work for Python 3.7.1. Check
https://travis-ci.org/eeriks/erepublik_script/pull_requests
and make sure that the tests pass for all supported Python versions.

View File

@ -2,6 +2,19 @@
History
=======
0.15.0 (2019-07-30)
-------------------
* CitizenAPI class methods renamed to "private", they are intended to be used internally.
* TODO: None of the Citizen class's methods should return Response object - CitizenAPI is meant for that.
0.14.4 (2019-07-23)
-------------------
* Wall post comment endpoints updated with comment create endpoints.
0.1.0 (2019-07-19)
------------------

View File

@ -51,7 +51,7 @@ clean-test: ## remove test and coverage artifacts
rm -fr .pytest_cache
lint: ## check style with flake8
flake8 erepublik_script tests
flake8 erepublik tests
test: ## run tests quickly with the default Python
python setup.py test
@ -60,15 +60,15 @@ test-all: ## run tests on every Python version with tox
tox
coverage: ## check code coverage quickly with the default Python
coverage run --source erepublik_script setup.py test
coverage run --source erepublik setup.py test
coverage report -m
coverage html
$(BROWSER) htmlcov/index.html
docs: ## generate Sphinx HTML documentation, including API docs
rm -f docs/erepublik_script.rst
rm -f docs/erepublik.rst
rm -f docs/modules.rst
sphinx-apidoc -o docs/ erepublik_script
sphinx-apidoc -o docs/ erepublik
$(MAKE) -C docs clean
$(MAKE) -C docs html
$(BROWSER) docs/_build/html/index.html

View File

@ -3,11 +3,11 @@ eRepublik script
================
.. image:: https://img.shields.io/pypi/v/erepublik_script.svg
:target: https://pypi.python.org/pypi/erepublik_script
.. image:: https://img.shields.io/pypi/v/erepublik.svg
:target: https://pypi.python.org/pypi/erepublik
.. image:: https://readthedocs.org/projects/erepublik-script/badge/?version=latest
:target: https://erepublik-script.readthedocs.io/en/latest/?badge=latest
.. image:: https://readthedocs.org/projects/erepublik_script/badge/?version=latest
:target: https://erepublik_script.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
@ -15,7 +15,7 @@ Python package for automated eRepublik playing
* Free software: MIT license
* Documentation: https://erepublik-script.readthedocs.io.
* Documentation: https://erepublik.readthedocs.io.
Features

View File

@ -4,7 +4,7 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python -msphinx
SPHINXPROJ = erepublik_script
SPHINXPROJ = erepublik
SOURCEDIR = .
BUILDDIR = _build

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# erepublik_script documentation build configuration file, created by
# erepublik documentation build configuration file, created by
# sphinx-quickstart on Fri Jun 9 13:47:02 2017.
#
# This file is execfile()d with the current directory set to its
@ -22,7 +22,7 @@ import os
import sys
sys.path.insert(0, os.path.abspath('..'))
import erepublik_script
import erepublik
# -- General configuration ---------------------------------------------
@ -56,9 +56,9 @@ author = u"Eriks Karls"
# the built documents.
#
# The short X.Y version.
version = erepublik_script.__version__
version = erepublik.__version__
# The full version, including alpha/beta/rc tags.
release = erepublik_script.__version__
release = erepublik.__version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -101,7 +101,7 @@ html_static_path = ['_static']
# -- Options for HTMLHelp output ---------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'erepublik_scriptdoc'
htmlhelp_basename = 'erepublikdoc'
# -- Options for LaTeX output ------------------------------------------
@ -128,7 +128,7 @@ latex_elements = {
# (source start file, target name, title, author, documentclass
# [howto, manual, or own class]).
latex_documents = [
(master_doc, 'erepublik_script.tex',
(master_doc, 'erepublik.tex',
u'eRepublik script Documentation',
u'Eriks Karls', 'manual'),
]
@ -139,7 +139,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'erepublik_script',
(master_doc, 'erepublik',
u'eRepublik script Documentation',
[author], 1)
]
@ -151,10 +151,10 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'erepublik_script',
(master_doc, 'erepublik',
u'eRepublik script Documentation',
author,
'erepublik_script',
'erepublik',
'One line description of project.',
'Miscellaneous'),
]

View File

@ -1,5 +1,5 @@
Welcome to eRepublik script's documentation!
======================================
============================================
.. toctree::
:maxdepth: 2

View File

@ -12,7 +12,7 @@ To install eRepublik script, run this command in your terminal:
.. code-block:: console
$ pip install erepublik_script
$ pip install erepublik
This is the preferred method to install eRepublik script, as it will always install the most recent stable release.

View File

@ -4,4 +4,4 @@ Usage
To use eRepublik script in a project::
import erepublik_script
import erepublik

View File

@ -4,8 +4,7 @@
__author__ = """Eriks Karls"""
__email__ = 'eriks@72.lv'
__version__ = '0.14.4'
from erepublik_script import classes, utils
from erepublik_script.citizen import Citizen
__version__ = '0.15.2'
from erepublik import classes, utils
from erepublik.citizen import Citizen

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
# pylint: disable=fixme, line-too-long, missing-docstring, invalid-name
import datetime
import decimal
import hashlib
@ -6,12 +5,11 @@ import random
import time
from collections import deque
from json import JSONDecodeError, loads, JSONEncoder
from typing import Any, Dict, List, Union
from typing import Any, Dict, List, Union, Mapping, Iterable
from requests import Response, Session
from slugify import slugify
from erepublik_script import utils
from erepublik import utils
class ErepublikException(Exception):
@ -28,11 +26,13 @@ class ErepublikNetworkException(Exception):
class MyCompanies:
work_units: int = 0
next_ot_time: datetime.datetime
holdings: Dict[int, Dict] = dict()
companies: Dict[int, Dict] = dict()
holdings: Dict[int, Dict] = None
companies: Dict[int, Dict] = None
ff_lockdown: int = 0
def __init__(self):
self.holdings = dict()
self.companies = dict()
self.next_ot_time = utils.now()
def prepare_holdings(self, holdings: dict):
@ -43,7 +43,7 @@ class MyCompanies:
template = dict(id=0, num_factories=0, region_id=0, companies=[])
for holding_id, holding in holdings.items():
tmp: Dict[str, Union[List[Any], Any]] = {}
tmp: Dict[str, Union[Iterable[Any], Any]] = {}
for key in template:
if key == 'companies':
tmp.update({key: []})
@ -223,12 +223,12 @@ class SlowRequests(Session):
body = "[{dt}]\tURL: '{url}'\tMETHOD: {met}\tARGS: {args}\n".format(dt=utils.now().strftime("%F %T"),
url=url, met=method, args=args)
utils.get_file(self.request_log_name)
with open(self.request_log_name, 'ab') as file:
file.write(body.encode("UTF-8"))
def _log_response(self, url, resp, redirect: bool = False):
from erepublik_script import Citizen
from erepublik import Citizen
if self.debug:
if resp.history and not redirect:
for hist_resp in resp.history:
@ -239,7 +239,7 @@ class SlowRequests(Session):
file_data = {
"path": 'debug/requests',
"time": self.last_time.strftime('%Y-%m-%d_%H-%M-%S'),
"name": slugify(url[len(Citizen.url):]),
"name": utils.slugify(url[len(Citizen.url):]),
"extra": "_REDIRECT" if redirect else ""
}
@ -438,10 +438,14 @@ class House(object):
class CitizenAPI:
url = "https://www.erepublik.com/en"
_req = SlowRequests
url: str = "https://www.erepublik.com/en"
_req: SlowRequests = None
token: str = ""
def __init__(self):
"""
Class for unifying eRepublik known endpoints and their required/optional parameters
"""
self._req = SlowRequests()
def post(self, url: str, *args, **kwargs) -> Response:
@ -450,112 +454,126 @@ class CitizenAPI:
def get(self, url: str, **kwargs) -> Response:
return self._req.get(url, **kwargs)
def get_article_json(self, article_id: int) -> Response:
def _get_article_json(self, article_id: int) -> Response:
return self.get("{}/main/articleJson/{}".format(self.url, article_id))
def get_battlefield_choose_side(self, battle: int, side: int) -> Response:
def _get_battlefield_choose_side(self, battle: int, side: int) -> Response:
return self.get("{}/military/battlefield-choose-side/{}/{}".format(self.url, battle, side))
def get_candidate_party(self, party_slug: str) -> Response:
def _get_candidate_party(self, party_slug: str) -> Response:
return self.post("{}/candidate/{}".format(self.url, party_slug))
def get_citizen_hovercard(self, citizen: int) -> Response:
def _get_citizen_hovercard(self, citizen: int) -> Response:
return self.get("{}/main/citizen-hovercard/{}".format(self.url, citizen))
def get_citizen_profile(self, player_id: int):
def _get_citizen_profile(self, player_id: int) -> Response:
return self.get("{}/main/citizen-profile-json/{}".format(self.url, player_id))
def get_citizen_daily_assistant(self):
def _get_citizen_daily_assistant(self) -> Response:
return self.get("{}/main/citizenDailyAssistant".format(self.url))
def get_city_data_residents(self, city: int, page: int = 1, params: Dict[str, Any] = {}):
def _get_city_data_residents(self, city: int, page: int = 1, params: Mapping[str, Any] = None) -> Response:
if params is None:
params = {}
return self.get("{}/main/city-data/{}/residents".format(self.url, city), params={"currentPage": page, **params})
def get_country_military(self, country: str) -> Response:
def _get_country_military(self, country: str) -> Response:
return self.get("{}/country/military/{}".format(self.url, country))
def get_economy_inventory_items(self) -> Response:
def _get_economy_inventory_items(self) -> Response:
return self.get("{}/economy/inventory-items/".format(self.url))
def get_economy_job_market_json(self, country: int) -> Response:
def _get_economy_job_market_json(self, country: int) -> Response:
return self.get("{}/economy/job-market-json/{}/1/desc".format(self.url, country))
def get_economy_my_companies(self) -> Response:
def _get_economy_my_companies(self) -> Response:
return self.get("{}/economy/myCompanies".format(self.url))
def get_economy_my_market_offers(self) -> Response:
def _get_economy_my_market_offers(self) -> Response:
return self.get("{}/economy/myMarketOffers".format(self.url))
def get_job_data(self) -> Response:
def _get_job_data(self) -> Response:
return self.get("{}/main/job-data".format(self.url))
def get_leaderboards_damage_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response:
def _get_leaderboards_damage_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response:
data = (country, weeks, mu)
return self.get("{}/main/leaderboards-damage-aircraft-rankings/{}/{}/{}/0".format(self.url, *data))
def get_leaderboards_damage_rankings(self, country: int, weeks: int = 0, mu: int = 0, div: int = 0) -> Response:
def _get_leaderboards_damage_rankings(self, country: int, weeks: int = 0, mu: int = 0, div: int = 0) -> Response:
data = (country, weeks, mu, div)
return self.get("{}/main/leaderboards-damage-rankings/{}/{}/{}/{}".format(self.url, *data))
def get_leaderboards_kills_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response:
def _get_leaderboards_kills_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response:
data = (country, weeks, mu)
return self.get("{}/main/leaderboards-kills-aircraft-rankings/{}/{}/{}/0".format(self.url, *data))
def get_leaderboards_kills_rankings(self, country: int, weeks: int = 0, mu: int = 0, div: int = 0) -> Response:
def _get_leaderboards_kills_rankings(self, country: int, weeks: int = 0, mu: int = 0, div: int = 0) -> Response:
data = (country, weeks, mu, div)
return self.get("{}/main/leaderboards-kills-rankings/{}/{}/{}/{}".format(self.url, *data))
def get_main(self):
def _get_main(self) -> Response:
return self.get(self.url)
def get_message_alerts(self, page: int = 1) -> Response:
return self.get_message_alerts(page)
def _get_messages(self, page: int = 1) -> Response:
return self.get("{}/main/messages-paginated/{}".format(self.url, page))
def get_military_campaigns(self) -> Response:
def _get_military_campaigns(self) -> Response:
return self.get("{}/military/campaigns-new/".format(self.url))
def get_military_unit_data(self, unit_id: int, page: int = 1) -> Response:
params = {"groupId": unit_id, "panel": "members", "currentPage": page}
def _get_military_unit_data(self, unit_id: int, **kwargs) -> Response:
params = {"groupId": unit_id, "panel": "members", **kwargs}
return self.get("{}/military/military-unit-data/".format(self.url), params=params)
def get_money_donation_accept(self, token: str, donation_id: int) -> Response:
return self.get("{}/main/money-donation/accept/{}".format(self.url, donation_id), params={"_token": token})
def _get_money_donation_accept(self, donation_id: int) -> Response:
return self.get("{}/main/money-donation/accept/{}".format(self.url, donation_id), params={"_token": self.token})
def get_money_donation_reject(self, token: str, donation_id: int) -> Response:
return self.get("{}/main/money-donation/reject/{}".format(self.url, donation_id), params={"_token": token})
def _get_money_donation_reject(self, donation_id: int) -> Response:
return self.get("{}/main/money-donation/reject/{}".format(self.url, donation_id), params={"_token": self.token})
def get_party_members(self, party: int) -> Response:
def _get_notifications_ajax_community(self, page: int = 1) -> Response:
return self.get("{}/main/notificationsAjax/community/{}".format(self.url, page))
def _get_notifications_ajax_system(self, page: int = 1) -> Response:
return self.get("{}/main/notificationsAjax/system/{}".format(self.url, page))
def _get_notifications_ajax_report(self, page: int = 1) -> Response:
return self.get("{}/main/notificationsAjax/report/{}".format(self.url, page))
def _get_party_members(self, party: int) -> Response:
return self.get("{}/main/party-members/{}".format(self.url, party))
def get_rankings_parties(self, country: int) -> Response:
def _get_rankings_parties(self, country: int) -> Response:
return self.get("{}/main/rankings-parties/1/{}".format(self.url, country))
def get_training_grounds_json(self) -> Response:
def _get_training_grounds_json(self) -> Response:
return self.get("{}/main/training-grounds-json".format(self.url))
def get_weekly_challenge_data(self) -> Response:
def _get_weekly_challenge_data(self) -> Response:
return self.get("{}/main/weekly-challenge-data".format(self.url))
def post_activate_battle_effect(self, token: str, battle: int, kind: str, citizen_id: int) -> Response:
data = dict(battleId=battle, citizenId=citizen_id, type=kind, _token=token)
def _get_wars_show(self, war_id: int) -> Response:
return self.get("{}/wars/show/{}".format(self.url, war_id))
def _post_activate_battle_effect(self, battle: int, kind: str, citizen_id: int) -> Response:
data = dict(battleId=battle, citizenId=citizen_id, type=kind, _token=self.token)
return self.post("{}/main/fight-activateBattleEffect".format(self.url), data=data)
def post_article_comments(self, token: str, article: int, page: int = 0) -> Response:
data = dict(_token=token, articleId=article, page=page)
def _post_article_comments(self, article: int, page: int = 1) -> Response:
data = dict(_token=self.token, articleId=article, page=page)
if page:
data.update({'page': page})
return self.post("{}/main/articleComments".format(self.url), data=data)
def post_article_comments_create(self, token: str, message: str, article: int, parent: int = 0) -> Response:
data = dict(_token=token, message=message, articleId=article)
def _post_article_comments_create(self, message: str, article: int, parent: int = 0) -> Response:
data = dict(_token=self.token, message=message, articleId=article)
if parent:
data.update({"parentId": parent})
return self.post("{}/main/articleComments/create".format(self.url), data=data)
def post_battle_console(self, token: str, battle: int, zone: int, round_id: int, division: int, page: int,
damage: bool) -> Response:
def _post_battle_console(self, battle: int, zone: int, round_id: int, division: int, page: int,
damage: bool) -> Response:
data = dict(battleId=battle, zoneId=zone, action="battleStatistics", round=round_id, division=division,
leftPage=page, rightPage=page, _token=token)
leftPage=page, rightPage=page, _token=self.token)
if damage:
data.update({"type": "damage"})
else:
@ -563,124 +581,125 @@ class CitizenAPI:
return self.post("{}/military/battle-console".format(self.url), data=data)
def post_buy_gold_items(self, token: str, currency: str, item: str, amount: int) -> Response:
data = dict(itemId=item, currency=currency, amount=amount, _token=token)
def _post_buy_gold_items(self, currency: str, item: str, amount: int) -> Response:
data = dict(itemId=item, currency=currency, amount=amount, _token=self.token)
return self.post("{}/main/buyGoldItems".format(self.url), data=data)
def post_candidate_for_congress(self, token: str, presentation: str = "") -> Response:
data = dict(_token=token, presentation=presentation)
def _post_candidate_for_congress(self, presentation: str = "") -> Response:
data = dict(_token=self.token, presentation=presentation)
return self.post("{}/candidate-for-congress".format(self.url), data=data)
def post_citizen_add_remove_friend(self, token: str, citizen: int, add: bool) -> Response:
data = dict(_token=token, citizenId=citizen, url="//www.erepublik.com/en/main/citizen-addRemoveFriend")
def _post_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")
if add:
data.update({"action": "addFriend"})
else:
data.update({"action": "removeFriend"})
return self.post("{}/main/citizen-addRemoveFriend".format(self.url), data=data)
def post_collect_anniversary_reward(self, token: str) -> Response:
return self.post("{}/main/collect-anniversary-reward".format(self.url), data={"_token": token})
def _post_collect_anniversary_reward(self) -> Response:
return self.post("{}/main/collect-anniversary-reward".format(self.url), data={"_token": self.token})
def post_country_donate(self, token: str, country: int, action: str, value: Union[int, float], quality: int = None):
json = dict(countryId=country, action=action, _token=token, value=value, quality=quality)
def _post_country_donate(self, country: int, action: str, value: Union[int, float],
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,
headers={"Referer": "{}/country/economy/Latvia".format(self.url)})
def post_daily_task_reward(self, token: str) -> Response:
return self.post("{}/main/daily-tasks-reward".format(self.url), data=dict(_token=token))
def _post_daily_task_reward(self) -> Response:
return self.post("{}/main/daily-tasks-reward".format(self.url), data=dict(_token=self.token))
def post_delete_message(self, token: str, msg_id: list) -> Response:
data = {"_token": token, "delete_message[]": msg_id}
def _post_delete_message(self, msg_id: list) -> Response:
data = {"_token": self.token, "delete_message[]": msg_id}
return self.post("{}/main/messages-delete".format(self.url), data)
def post_eat(self, token: str, color: str) -> Response:
data = dict(_token=token, buttonColor=color)
def _post_eat(self, color: str) -> Response:
data = dict(_token=self.token, buttonColor=color)
return self.post("{}/main/eat".format(self.url), params=data)
def post_economy_activate_house(self, token: str, quality: int) -> Response:
data = {"action": "activate", "quality": quality, "type": "house", "_token": token}
def _post_economy_activate_house(self, quality: int) -> Response:
data = {"action": "activate", "quality": quality, "type": "house", "_token": self.token}
return self.post("{}/economy/activateHouse".format(self.url), data=data)
def post_economy_assign_to_holding(self, token: str, factory: int, holding: int) -> Response:
data = dict(_token=token, factoryId=factory, action="assign", holdingCompanyId=holding)
def _post_economy_assign_to_holding(self, factory: int, holding: int) -> Response:
data = dict(_token=self.token, factoryId=factory, action="assign", holdingCompanyId=holding)
return self.post("{}/economy/assign-to-holding".format(self.url), data=data)
def post_economy_create_company(self, token: str, industry: int, building_type: int = 1) -> Response:
data = {"_token": token, "company[industry_id]": industry, "company[building_type]": building_type}
def _post_economy_create_company(self, industry: int, building_type: int = 1) -> Response:
data = {"_token": self.token, "company[industry_id]": industry, "company[building_type]": building_type}
return self.post("{}/economy/create-company".format(self.url), data=data,
headers={"Referer": "{}/economy/create-company".format(self.url)})
def post_economy_donate_items_action(self, token: str, citizen: int, amount: int, industry: int,
quality: int) -> Response:
data = dict(citizen_id=citizen, amount=amount, industry_id=industry, quality=quality, _token=token)
def _post_economy_donate_items_action(self, citizen: int, amount: int, industry: int,
quality: int) -> Response:
data = dict(citizen_id=citizen, amount=amount, industry_id=industry, quality=quality, _token=self.token)
return self.post("{}/economy/donate-items-action".format(self.url), data=data,
headers={"Referer": "{}/economy/donate-items/{}".format(self.url, citizen)})
def post_economy_donate_money_action(self, token: str, citizen: int, amount: float = 0.0,
currency: int = 62) -> Response:
data = dict(citizen_id=citizen, _token=token, currency_id=currency, amount=amount)
def _post_economy_donate_money_action(self, citizen: int, amount: float = 0.0,
currency: int = 62) -> Response:
data = dict(citizen_id=citizen, _token=self.token, currency_id=currency, amount=amount)
return self.post("{}/economy/donate-money-action".format(self.url), data=data,
headers={"Referer": "{}/economy/donate-money/{}".format(self.url, citizen)})
def post_economy_exchange_purchase(self, token: str, amount: float, currency: int, offer: int) -> Response:
data = dict(_token=token, amount=amount, currencyId=currency, offerId=offer)
def _post_economy_exchange_purchase(self, amount: float, currency: int, offer: int) -> Response:
data = dict(_token=self.token, amount=amount, currencyId=currency, offerId=offer)
return self.post("{}/economy/exchange/purchase/".format(self.url), data=data)
def post_economy_exchange_retrieve(self, token: str, personal: bool, page: int, currency: int) -> Response:
data = dict(_token=token, personalOffers=int(personal), page=page, currencyId=currency)
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)
return self.post("{}/economy/exchange/retrieve/".format(self.url), data=data)
def post_economy_job_market_apply(self, token: str, citizen: int, salary: int) -> Response:
data = dict(_token=token, citizenId=citizen, salary=salary)
def _post_economy_job_market_apply(self, citizen: int, salary: int) -> Response:
data = dict(_token=self.token, citizenId=citizen, salary=salary)
return self.post("{}/economy/job-market-apply".format(self.url), data=data)
def post_economy_marketplace(self, token: str, country: int, industry: int, quality: int,
order_asc: bool = True) -> Response:
def _post_economy_marketplace(self, country: int, industry: int, quality: int,
order_asc: bool = True) -> Response:
data = dict(countryId=country, industryId=industry, quality=quality, ajaxMarket=1,
orderBy="price_asc" if order_asc else "price_desc", _token=token)
orderBy="price_asc" if order_asc else "price_desc", _token=self.token)
return self.post("{}/economy/marketplaceAjax".format(self.url), data=data)
def post_economy_marketplace_actions(self, token: str, amount: int, buy: bool = False, **kwargs) -> Response:
def _post_economy_marketplace_actions(self, amount: int, buy: bool = False, **kwargs) -> Response:
if buy:
data = dict(_token=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)
else:
data = dict(_token=token, countryId=kwargs["country"], price=kwargs["price"], industryId=kwargs["industry"],
quality=kwargs["quality"], amount=amount, sellAction='postOffer')
data = dict(_token=self.token, countryId=kwargs["country"], price=kwargs["price"],
industryId=kwargs["industry"], quality=kwargs["quality"], amount=amount, sellAction='postOffer')
return self.post("{}/economy/marketplaceActions".format(self.url), data=data)
def post_economy_resign(self, token: str) -> Response:
def _post_economy_resign(self) -> Response:
return self.post("{}/economy/resign".format(self.url),
headers={"Content-Type": "application/x-www-form-urlencoded"},
data={"_token": token, "action_type": "resign"})
data={"_token": self.token, "action_type": "resign"})
def post_economy_sell_company(self, token: str, factory: int, pin: int = None, sell: bool = True) -> Response:
def _post_economy_sell_company(self, factory: int, pin: int = None, sell: bool = True) -> Response:
url = "{}/economy/sell-company/{}".format(self.url, factory)
data = dict(_token=token, pin="" if pin is None else pin)
data = dict(_token=self.token, pin="" if pin is None else pin)
if sell:
data.update({"sell": "sell"})
else:
data.update({"dissolve": factory})
return self.post(url, data=data, headers={"Referer": url})
def post_economy_train(self, token: str, tg_ids: List[int]) -> Response:
def _post_economy_train(self, tg_ids: List[int]) -> Response:
data: Dict[str, Union[int, str]] = {}
if not tg_ids:
return self.get_training_grounds_json()
return self._get_training_grounds_json()
else:
for idx, tg_id in enumerate(tg_ids):
data["grounds[%i][id]" % idx] = tg_id
data["grounds[%i][train]" % idx] = 1
if data:
data['_token'] = token
data['_token'] = self.token
return self.post("{}/economy/train".format(self.url), data=data)
def post_economy_upgrade_company(self, token: str, factory: int, level: int, pin: str = None) -> Response:
data = dict(_token=token, type="upgrade", companyId=factory, level=level, pin="" if pin is None else pin)
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)
return self.post("{}/economy/upgrade-company".format(self.url), data=data)
def post_economy_work(self, token: str, action_type: str, wam: List[int] = None, employ: Dict[int, int] = None):
def _post_economy_work(self, action_type: str, wam: List[int] = None, employ: Dict[int, int] = None) -> Response:
"""
:return: requests.Response or None
"""
@ -688,163 +707,167 @@ class CitizenAPI:
employ = dict()
if wam is None:
wam = []
data: Dict[str, Union[int, str]] = dict(action_type=action_type, _token=token)
if action_type == "work":
return self.post("{}/economy/work".format(self.url), data=data)
elif action_type == "production":
data: Dict[str, Union[int, str]] = dict(action_type=action_type, _token=self.token)
if action_type == "production":
max_idx = 0
for idx, company_id in enumerate(sorted(wam or [])):
for company_id in sorted(wam or []):
data.update({
"companies[%i][id]" % idx: company_id,
"companies[%i][employee_works]" % idx: employ.pop(company_id, 0),
"companies[%i][own_work]" % idx: 1
"companies[%i][id]" % max_idx: company_id,
"companies[%i][employee_works]" % max_idx: employ.pop(company_id, 0),
"companies[%i][own_work]" % max_idx: 1
})
max_idx = idx + 1
for idx, company_id in enumerate(sorted(employ or [])):
idx_ = idx + max_idx
max_idx += 1
for company_id in sorted(employ or []):
data.update({
"companies[%i][id]" % idx_: company_id,
"companies[%i][employee_works]" % idx_: employ.pop(company_id),
"companies[%i][own_work]" % idx_: 0
"companies[%i][id]" % max_idx: company_id,
"companies[%i][employee_works]" % max_idx: employ.pop(company_id),
"companies[%i][own_work]" % max_idx: 0
})
return self.post("{}/economy/work".format(self.url), data=data)
else:
return
max_idx += 1
return self.post("{}/economy/work".format(self.url), data=data)
def post_economy_work_overtime(self, token: str) -> Response:
data = dict(action_type="workOvertime", _token=token)
def _post_economy_work_overtime(self) -> Response:
data = dict(action_type="workOvertime", _token=self.token)
return self.post("{}/economy/workOvertime".format(self.url), data=data)
def post_forgot_password(self, token: str, email: str) -> Response:
data = dict(_token=token, email=email, commit="Reset password")
def _post_forgot_password(self, email: str) -> Response:
data = dict(_token=self.token, email=email, commit="Reset password")
return self.post("{}/forgot-password".format(self.url), data=data)
def post_fight_activate_booster(self, token: str, battle: int, quality: int, duration: int, kind: str) -> Response:
data = dict(type=kind, quality=quality, duration=duration, battleId=battle, _token=token)
def _post_fight_activate_booster(self, battle: int, quality: int, duration: int, kind: str) -> Response:
data = dict(type=kind, quality=quality, duration=duration, battleId=battle, _token=self.token)
return self.post("{}/military/fight-activateBooster".format(self.url), data=data)
def post_login(self, token: str, email: str, password: str) -> Response:
data = dict(csrf_token=token, citizen_email=email, citizen_password=password, remember='on')
def _post_login(self, email: str, password: str) -> Response:
data = dict(csrf_token=self.token, citizen_email=email, citizen_password=password, remember='on')
return self.post("{}/login".format(self.url), data=data)
def post_messages_alert(self, token: str, notification_ids: list) -> Response:
data = {"_token": token, "delete_alerts[]": notification_ids, "deleteAllAlerts": "1", "delete": "Delete"}
def _post_messages_alert(self, notification_ids: List[int]) -> Response:
data = {"_token": self.token, "delete_alerts[]": notification_ids, "deleteAllAlerts": "1", "delete": "Delete"}
return self.post("{}/main/messages-alerts/1".format(self.url), data=data)
def post_messages_compose(self, token: str, subject: str, body: str, citizens: List[int]) -> Response:
def _post_messages_compose(self, subject: str, body: str, citizens: List[int]) -> Response:
url_pk = 0 if len(citizens) > 1 else str(citizens[0])
data = dict(citizen_name=",".join([str(x) for x in citizens]),
citizen_subject=subject, _token=token, citizen_message=body)
citizen_subject=subject, _token=self.token, citizen_message=body)
return self.post("{}/main/messages-compose/{}}".format(self.url, url_pk), data=data)
def post_military_battle_console(self, token: str, battle_id: int, round_id: int, division: int) -> Response:
data = dict(battleId=battle_id, zoneId=round_id, action="battleStatistics", round=round_id, division=division,
type="damage", leftPage=1, rightPage=1, _token=token)
return self.post("{}/military/battle-console".format(self.url, battle_id), data=data)
def _post_military_battle_console(self, battle_id: int, action: str, page: int = 1, **kwargs) -> Response:
data = dict(battleId=battle_id, action=action, _token=self.token)
if action == "battleStatistics":
data.update(round=kwargs["round_id"], zoneId=kwargs["round_id"], leftPage=page, rightPage=page,
division=kwargs["division"], type=kwargs.get("type", 'damage'),)
elif action == "warList":
data.update(page=page)
return self.post("{}/military/battle-console".format(self.url), data=data)
def post_military_fight_air(self, token: str, battle_id: int, side_id: int) -> Response:
data = dict(sideId=side_id, battleId=battle_id, _token=token)
def _post_military_deploy_bomb(self, battle_id: int, bomb_id: int) -> Response:
data = dict(battleId=battle_id, bombId=bomb_id, _token=self.token)
return self.post("{}/military/deploy-bomb".format(self.url), data=data)
def _post_military_fight_air(self, battle_id: int, side_id: int) -> Response:
data = dict(sideId=side_id, battleId=battle_id, _token=self.token)
return self.post("{}/military/fight-shoooot/{}".format(self.url, battle_id), data=data)
def post_military_fight_ground(self, token: str, battle_id: int, side_id: int) -> Response:
data = dict(sideId=side_id, battleId=battle_id, _token=token)
def _post_military_fight_ground(self, battle_id: int, side_id: int) -> Response:
data = dict(sideId=side_id, battleId=battle_id, _token=self.token)
return self.post("{}/military/fight-shooot/{}".format(self.url, battle_id), data=data)
def post_military_group_missions(self, token: str) -> Response:
data = dict(action="check", _token=token)
def _post_military_group_missions(self) -> Response:
data = dict(action="check", _token=self.token)
return self.post("{}/military/group-missions".format(self.url), data=data)
def post_travel(self, token: str, check: str, **kwargs) -> Response:
data = dict(_token=token, check=check, **kwargs)
def _post_travel(self, check: str, **kwargs) -> Response:
data = dict(_token=self.token, check=check, **kwargs)
return self.post("{}/main/travel".format(self.url), data=data)
def post_travel_data(self, token: str, **kwargs) -> Response:
return self.post("{}/main/travelData".format(self.url), data=dict(_token=token, **kwargs))
def _post_travel_data(self, **kwargs) -> Response:
return self.post("{}/main/travelData".format(self.url), data=dict(_token=self.token, **kwargs))
def post_wars_attack_region(self, token: str, war: int, region: int) -> Response:
data = dict(_token=token)
return self.post("{}/wars/attack-region/{}/{}".format(self.url, war, region), data=data)
def _post_wars_attack_region(self, war_id: int, region_id: int, region_name: str) -> Response:
data = {'_token': self.token, 'warId': war_id, 'regionName': region_name, 'regionNameConfirm': region_name}
return self.post('{}/wars/attack-region/{}/{}'.format(self.url, war_id, region_id), data=data)
def post_weekly_challenge_reward(self, token: str, reward_id: int) -> Response:
data = dict(_token=token, rewardId=reward_id)
def _post_weekly_challenge_reward(self, reward_id: int) -> Response:
data = dict(_token=self.token, rewardId=reward_id)
return self.post("{}/main/weekly-challenge-collect-reward".format(self.url), data=data)
def post_write_article(self, token: str, title: str, content: str, location: int, kind: int) -> Response:
data = dict(_token=token, article_name=title, article_body=content, article_location=location,
def _post_write_article(self, title: str, content: str, location: int, kind: int) -> Response:
data = dict(_token=self.token, article_name=title, article_body=content, article_location=location,
article_category=kind)
return self.post("{}/main/write-article".format(self.url), data=data)
# Wall Posts
# ## Country
def post_country_comment_retrieve(self, token: str, post_id: int):
data = {"_token": token, "postId": post_id}
def _post_country_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/country-comment/retrieve/json".format(self.url), data=data)
def post_country_comment_create(self, token: str, post_id: int, comment_message: str):
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
def _post_country_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/country-comment/create/json".format(self.url), data=data)
def post_country_post_create(self, token: str, body: str, post_as: int):
data = {"_token": token, "post_message": body, "post_as": post_as}
def _post_country_post_create(self, body: str, post_as: int) -> Response:
data = {"_token": self.token, "post_message": body, "post_as": post_as}
return self.post("{}/main/country-post/create/json".format(self.url), data=data)
def post_country_post_retrieve(self, token: str):
data = {"_token": token, "page": 1, "switchedFrom": False}
def _post_country_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/country-post/retrieve/json".format(self.url), data=data)
# ## Military Unit
def post_military_unit_comment_retrieve(self, token: str, post_id: int):
data = {"_token": token, "postId": post_id}
def _post_military_unit_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/military-unit-comment/retrieve/json".format(self.url), data=data)
def post_military_unit_comment_create(self, token: str, post_id: int, comment_message: str):
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
def _post_military_unit_comment_create(self, post_id: int, comment_message: str) -> Response:
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)
def post_military_unit_post_create(self, token: str, body: str, post_as: int):
data = {"_token": token, "post_message": body, "post_as": post_as}
def _post_military_unit_post_create(self, body: str, post_as: int) -> Response:
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)
def post_military_unit_post_retrieve(self, token: str):
data = {"_token": token, "page": 1, "switchedFrom": False}
def _post_military_unit_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/military-unit-post/retrieve/json".format(self.url), data=data)
# ## Party
def post_party_comment_retrieve(self, token: str, post_id: int):
data = {"_token": token, "postId": post_id}
def _post_party_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/party-comment/retrieve/json".format(self.url), data=data)
def post_party_comment_create(self, token: str, post_id: int, comment_message: str):
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
def _post_party_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/party-comment/create/json".format(self.url), data=data)
def post_party_post_create(self, token: str, body: str):
data = {"_token": token, "post_message": body}
def _post_party_post_create(self, body: str) -> Response:
data = {"_token": self.token, "post_message": body}
return self.post("{}/main/party-post/create/json".format(self.url), data=data)
def post_party_post_retrieve(self, token: str):
data = {"_token": token, "page": 1, "switchedFrom": False}
def _post_party_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/party-post/retrieve/json".format(self.url), data=data)
# ## Friend's Wall
def post_wall_comment_retrieve(self, token: str, post_id: int):
data = {"_token": token, "postId": post_id}
def _post_wall_comment_retrieve(self, post_id: int) -> Response:
data = {"_token": self.token, "postId": post_id}
return self.post("{}/main/wall-comment/retrieve/json".format(self.url), data=data)
def post_wall_comment_create(self, token: str, post_id: int, comment_message: str):
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
def _post_wall_comment_create(self, post_id: int, comment_message: str) -> Response:
data = {"_token": self.token, "postId": post_id, 'comment_message': comment_message}
return self.post("{}/main/wall-comment/create/json".format(self.url), data=data)
def post_wall_post_create(self, token: str, body: str):
data = {"_token": token, "post_message": body}
def _post_wall_post_create(self, body: str) -> Response:
data = {"_token": self.token, "post_message": body}
return self.post("{}/main/wall-post/create/json".format(self.url), data=data)
def post_wall_post_retrieve(self, token: str):
data = {"_token": token, "page": 1, "switchedFrom": False}
def _post_wall_post_retrieve(self) -> Response:
data = {"_token": self.token, "page": 1, "switchedFrom": False}
return self.post("{}/main/wall-post/retrieve/json".format(self.url), data=data)
@ -938,7 +961,7 @@ class MyJSONEncoder(JSONEncoder):
return dict(__type__='timedelta', days=o.days, seconds=o.seconds,
microseconds=o.microseconds, total_seconds=o.total_seconds())
elif isinstance(o, Response):
return dict(_content=o._content.decode("UTF-8"), headers=o.headers.__dict__, url=o.url, text=o.text)
return dict(headers=o.headers.__dict__, url=o.url, text=o.text)
elif hasattr(o, '__dict__'):
return o.__dict__
elif isinstance(o, deque):
@ -949,8 +972,8 @@ class MyJSONEncoder(JSONEncoder):
class BattleSide:
id: int
points: int
deployed: List[int] = list()
allies: List[int] = list()
deployed: List[int] = None
allies: List[int] = None
def __init__(self, country_id: int, points: int, allies: List[int], deployed: List[int]):
self.id = country_id
@ -962,8 +985,8 @@ class BattleSide:
class BattleDivision:
end: datetime.datetime
epic: bool
dom_pts: Dict[str, int] = dict()
wall: Dict[str, Union[int, float]] = dict()
dom_pts: Dict[str, int] = None
wall: Dict[str, Union[int, float]] = None
@property
def div_end(self) -> bool:
@ -972,8 +995,8 @@ class BattleDivision:
def __init__(self, end: datetime.datetime, epic: bool, inv_pts: int, def_pts: int, wall_for: int, wall_dom: float):
self.end = end
self.epic = epic
self.dom_pts.update({"inv": inv_pts, "def": def_pts})
self.wall.update({"for": wall_for, "dom": wall_dom})
self.dom_pts = dict({"inv": inv_pts, "def": def_pts})
self.wall = dict({"for": wall_for, "dom": wall_dom})
class Battle(object):
@ -985,13 +1008,13 @@ class Battle(object):
start: datetime.datetime = None
invader: BattleSide = None
defender: BattleSide = None
div: Dict[int, BattleDivision] = dict()
div: Dict[int, BattleDivision] = None
@property
def is_air(self) -> bool:
return not bool(self.zone_id % 4)
def __init__(self, battle: dict):
def __init__(self, battle: Dict[str, Any]):
self.id = int(battle.get('id', 0))
self.war_id = int(battle.get('war_id', 0))
self.zone_id = int(battle.get('zone_id', 0))
@ -1008,6 +1031,7 @@ class Battle(object):
[row.get('id') for row in battle.get('def', {}).get('ally_list')],
[row.get('id') for row in battle.get('def', {}).get('ally_list') if row['deployed']])
self.div = {}
for div, data in battle.get('div', {}).items():
div = int(div)
if data.get('end'):

View File

@ -6,17 +6,16 @@ import re
import sys
import time
import traceback
import unicodedata
from collections import deque
from decimal import Decimal
from json import JSONEncoder
from pathlib import Path
from typing import Union
from typing import Union, Any, List, NoReturn, Mapping
import pytz
import requests
from requests import Response
from slugify import slugify
__all__ = ["FOOD_ENERGY", "COMMIT_ID", "COUNTRIES", "erep_tz",
"now", "localize_dt", "localize_timestamp", "good_timedelta", "eday_from_date", "date_from_eday",
@ -85,6 +84,19 @@ COUNTRIES = {1: 'Romania', 9: 'Brazil', 10: 'Italy', 11: 'France', 12: 'Germany'
82: 'Cyprus', 83: 'Belarus', 84: 'New Zealand', 164: 'Saudi Arabia', 165: 'Egypt',
166: 'United Arab Emirates', 167: 'Albania', 168: 'Georgia', 169: 'Armenia', 170: 'Nigeria', 171: 'Cuba'}
COUNTRY_LINK = {1: 'Romania', 9: 'Brazil', 11: 'France', 12: 'Germany', 13: 'Hungary', 82: 'Cyprus', 168: 'Georgia',
15: 'Spain', 23: 'Canada', 26: 'Mexico', 27: 'Argentina', 28: 'Venezuela', 80: 'Montenegro', 24: 'USA',
29: 'United-Kingdom', 50: 'Australia', 47: 'South-Korea',171: 'Cuba', 79: 'Republic-of-Macedonia-FYROM',
30: 'Switzerland', 31: 'Netherlands', 32: 'Belgium', 33: 'Austria', 34: 'Czech-Republic', 35: 'Poland',
36: 'Slovakia', 37: 'Norway', 38: 'Sweden', 39: 'Finland', 40: 'Ukraine', 41: 'Russia', 42: 'Bulgaria',
43: 'Turkey', 44: 'Greece', 45: 'Japan', 48: 'India', 49: 'Indonesia', 78: 'Colombia', 68: 'Singapore',
51: 'South Africa', 52: 'Republic-of-Moldova', 53: 'Portugal', 54: 'Ireland', 55: 'Denmark', 56: 'Iran',
57: 'Pakistan', 58: 'Israel', 59: 'Thailand', 61: 'Slovenia', 63: 'Croatia', 64: 'Chile', 65: 'Serbia',
66: 'Malaysia', 67: 'Philippines', 70: 'Estonia', 165: 'Egypt', 14: 'China', 77: 'Peru', 10: 'Italy',
71: 'Latvia', 72: 'Lithuania', 73: 'North-Korea', 74: 'Uruguay', 75: 'Paraguay', 76: 'Bolivia',
81: 'Republic-of-China-Taiwan', 166: 'United-Arab-Emirates', 167: 'Albania', 69: 'Bosnia-Herzegovina',
169: 'Armenia', 83: 'Belarus', 84: 'New-Zealand', 164: 'Saudi-Arabia', 170: 'Nigeria', }
class MyJSONEncoder(JSONEncoder):
def default(self, o):
@ -107,18 +119,22 @@ class MyJSONEncoder(JSONEncoder):
return super().default(o)
def now():
def now() -> datetime.datetime:
return datetime.datetime.now(erep_tz).replace(microsecond=0)
def localize_timestamp(timestamp: int):
def localize_timestamp(timestamp: int) -> datetime.datetime:
return datetime.datetime.fromtimestamp(timestamp, erep_tz)
def localize_dt(dt: Union[datetime.date, datetime.datetime]):
if isinstance(dt, datetime.date):
dt = datetime.datetime.combine(dt, datetime.time(0, 0, 0))
return erep_tz.localize(dt)
def localize_dt(dt: Union[datetime.date, datetime.datetime]) -> datetime.datetime:
try:
try:
return erep_tz.localize(dt)
except AttributeError:
return erep_tz.localize(datetime.datetime.combine(dt, datetime.time(0, 0, 0)))
except ValueError:
return dt.astimezone(erep_tz)
def good_timedelta(dt: datetime.datetime, td: datetime.timedelta) -> datetime.datetime:
@ -214,7 +230,7 @@ def write_file(filename: str, content: str) -> int:
def write_request(response: requests.Response, is_error: bool = False):
from erepublik_script import Citizen
from erepublik import Citizen
# Remove GET args from url name
url = response.url
last_index = url.index("?") if "?" in url else len(response.url)
@ -237,8 +253,11 @@ def write_request(response: requests.Response, is_error: bool = False):
"mimetype": "application/json" if ext == "json" else "text/html"}
def send_email(name, content: list, player=None, local_vars=dict, promo: bool = False, captcha: bool = False):
from erepublik_script import Citizen
def send_email(name: str, content: List[Any], player=None, local_vars: Mapping[Any, Any] = None,
promo: bool = False, captcha: bool = False):
if local_vars is None:
local_vars = {}
from erepublik import Citizen
file_content_template = "<html><head><title>{title}</title></head><body>{body}</body></html>"
if isinstance(player, Citizen):
@ -296,7 +315,6 @@ def process_error(log_info: str, name: str, exc_info: tuple, citizen=None, commi
interactive: bool = False):
"""
Process error logging and email sending to developer
:param error:
:param interactive: Should print interactively
:param log_info: String to be written in output
:param name: String Instance name
@ -312,4 +330,29 @@ def process_error(log_info: str, name: str, exc_info: tuple, citizen=None, commi
write_interactive_log(log_info)
else:
write_silent_log(log_info)
send_email(name, bugtrace, citizen, local_vars=inspect.trace()[-1][0].f_locals)
trace = inspect.trace()
if trace:
trace = trace[-1][0].f_locals
else:
trace = dict()
send_email(name, bugtrace, citizen, local_vars=trace)
def report_promo(kind: str, time_untill: datetime.datetime) -> NoReturn:
requests.post('https://api.erep.lv/promos/add/', data=dict(kind=kind, time_untill=time_untill))
def slugify(value, allow_unicode=False) -> str:
"""
Function copied from Django2.2.1 django.utils.text.slugify
Convert to ASCII if 'allow_unicode' is False. Convert spaces to hyphens.
Remove characters that aren't alphanumerics, underscores, or hyphens.
Convert to lowercase. Also strip leading and trailing whitespace.
"""
value = str(value)
if allow_unicode:
value = unicodedata.normalize('NFKC', value)
else:
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
value = re.sub(r'[^\w\s-]', '', value).strip().lower()
return re.sub(r'[-\s]+', '-', value)

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.14.4
current_version = 0.15.2
commit = True
tag = True
@ -7,7 +7,7 @@ tag = True
search = version='{current_version}'
replace = version='{new_version}'
[bumpversion:file:erepublik_script/__init__.py]
[bumpversion:file:erepublik/__init__.py]
search = __version__ = '{current_version}'
replace = __version__ = '{new_version}'
@ -17,7 +17,7 @@ universal = 1
[flake8]
exclude = docs
max-line-length = 120
ignore = E722
ignore = E722 F401
[aliases]

View File

@ -11,7 +11,7 @@ with open('README.rst') as readme_file:
with open('HISTORY.rst') as history_file:
history = history_file.read()
requirements = ['pytz==2019.1', 'requests==2.22.0', 'python-slugify<3.0.0']
requirements = ['pytz==2019.1', 'requests==2.22.0']
setup_requirements = [ ]
@ -21,26 +21,27 @@ setup(
author="Eriks Karls",
author_email='eriks@72.lv',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
],
description="Python package for eRepublik automated playing",
description="Python package for automated eRepublik playing",
entry_points={},
install_requires=requirements,
license="MIT license",
long_description=readme + '\n\n' + history,
include_package_data=True,
keywords='erepublik_script',
name='erepublik_script',
packages=find_packages(include=['erepublik_script']),
keywords='erepublik',
name='eRepublik',
packages=find_packages(include=['erepublik']),
python_requires='>=3.7.*, <4',
setup_requires=setup_requirements,
test_suite='tests',
tests_require=test_requirements,
url='https://github.com/eeriks/erepublik_script',
version='0.14.4',
version='0.15.2',
zip_safe=False,
)

View File

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Unit test package for erepublik_script."""
"""Unit test package for erepublik."""

View File

@ -1,18 +1,18 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests for `erepublik_script` package."""
"""Tests for `erepublik` package."""
import unittest
from click.testing import CliRunner
from erepublik_script import Citizen
from erepublik_script import cli
from erepublik import Citizen
from erepublik import cli
class TestErepublik_script(unittest.TestCase):
"""Tests for `erepublik_script` package."""
"""Tests for `erepublik` package."""
def setUp(self):
"""Set up test fixtures, if any."""
@ -28,7 +28,7 @@ class TestErepublik_script(unittest.TestCase):
runner = CliRunner()
result = runner.invoke(cli.main)
assert result.exit_code == 0
assert 'erepublik_script.cli.main' in result.output
assert 'erepublik.cli.main' in result.output
help_result = runner.invoke(cli.main, ['--help'])
assert help_result.exit_code == 0
assert '--help Show this message and exit.' in help_result.output