Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
61be2b1edf | |||
ce9034ad24 | |||
69b2073b74 | |||
eb048bf9f8 | |||
fe1206dc84 | |||
a2a1ed3dad | |||
39c8f6913e | |||
d7b15b3708 | |||
4fe3efa045 | |||
14bcb46735 | |||
b04cc896d8 | |||
f07062788b | |||
4504bdaa97 | |||
ac135614cc | |||
41752e1f2e | |||
a1739e627e | |||
12ff11deea | |||
4e3a16b8d4 | |||
5f56f59ab8 | |||
50c66efbda | |||
47b3154c6a | |||
632e4e8ad2 | |||
7c0d66f126 | |||
842fb64dae | |||
b22349cb1a | |||
a9ced91741 |
@ -4,7 +4,7 @@
|
||||
|
||||
__author__ = """Eriks Karls"""
|
||||
__email__ = 'eriks@72.lv'
|
||||
__version__ = '0.24.0.5'
|
||||
__version__ = '0.24.1'
|
||||
|
||||
from erepublik import classes, constants, utils
|
||||
from erepublik.citizen import Citizen
|
||||
|
@ -5,15 +5,15 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
import weakref
|
||||
from logging import LogRecord, handlers
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Union
|
||||
|
||||
import requests
|
||||
from logging import handlers, LogRecord
|
||||
from typing import Union, Dict, Any
|
||||
|
||||
from erepublik.classes import Reporter
|
||||
from erepublik.constants import erep_tz
|
||||
from erepublik.utils import slugify, json_loads, json, now, json_dumps
|
||||
from erepublik.utils import json, json_dumps, json_loads, slugify
|
||||
|
||||
|
||||
class ErepublikFileHandler(handlers.TimedRotatingFileHandler):
|
||||
@ -25,7 +25,7 @@ class ErepublikFileHandler(handlers.TimedRotatingFileHandler):
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
at_time = erep_tz.localize(datetime.datetime.now()).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
kwargs.update(atTime=at_time)
|
||||
super().__init__(filename, *args, **kwargs)
|
||||
super().__init__(filename, when='d', *args, **kwargs)
|
||||
|
||||
def doRollover(self) -> None:
|
||||
self._file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
@ -52,6 +52,18 @@ class ErepublikFormatter(logging.Formatter):
|
||||
return datetime.datetime.utcfromtimestamp(timestamp).astimezone(erep_tz)
|
||||
|
||||
def format(self, record: logging.LogRecord) -> str:
|
||||
"""
|
||||
Format the specified record as text.
|
||||
|
||||
The record's attribute dictionary is used as the operand to a
|
||||
string formatting operation which yields the returned string.
|
||||
Before formatting the dictionary, a couple of preparatory steps
|
||||
are carried out. The message attribute of the record is computed
|
||||
using LogRecord.getMessage(). If the formatting string uses the
|
||||
time (as determined by a call to usesTime(), formatTime() is
|
||||
called to format the event time. If there is exception information,
|
||||
it is formatted using formatException() and appended to the message.
|
||||
"""
|
||||
if record.levelno == logging.DEBUG:
|
||||
self._fmt = self.dbg_fmt
|
||||
elif record.levelno == logging.INFO:
|
||||
@ -59,7 +71,17 @@ class ErepublikFormatter(logging.Formatter):
|
||||
else:
|
||||
self._fmt = self.default_fmt
|
||||
self._style = logging.PercentStyle(self._fmt)
|
||||
return super().format(record)
|
||||
|
||||
record.message = record.getMessage()
|
||||
if self.usesTime():
|
||||
record.asctime = self.formatTime(record, self.datefmt)
|
||||
s = self.formatMessage(record)
|
||||
if record.exc_info:
|
||||
# Cache the traceback text to avoid converting it multiple times
|
||||
# (it's constant anyway)
|
||||
if not record.exc_text:
|
||||
record.exc_text = self.formatException(record.exc_info)
|
||||
return s
|
||||
|
||||
def formatTime(self, record, datefmt=None):
|
||||
dt = self.converter(record.created)
|
||||
@ -69,6 +91,9 @@ class ErepublikFormatter(logging.Formatter):
|
||||
s = dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
return s
|
||||
|
||||
def usesTime(self):
|
||||
return self._style.usesTime()
|
||||
|
||||
|
||||
class ErepublikErrorHTTTPHandler(handlers.HTTPHandler):
|
||||
def __init__(self, reporter: Reporter):
|
||||
@ -85,10 +110,7 @@ class ErepublikErrorHTTTPHandler(handlers.HTTPHandler):
|
||||
def reporter(self):
|
||||
return self._reporter()
|
||||
|
||||
def mapLogRecord(self, record: logging.LogRecord) -> Dict[str, Any]:
|
||||
data = super().mapLogRecord(record)
|
||||
|
||||
# Log last response
|
||||
def _get_last_response(self) -> Dict[str, str]:
|
||||
response = self.reporter.citizen.r
|
||||
url = response.url
|
||||
last_index = url.index("?") if "?" in url else len(response.url)
|
||||
@ -107,14 +129,10 @@ class ErepublikErrorHTTTPHandler(handlers.HTTPHandler):
|
||||
).replace(tzinfo=datetime.timezone.utc).astimezone(erep_tz).strftime('%F_%H-%M-%S')
|
||||
except:
|
||||
resp_time = slugify(response.headers.get('date'))
|
||||
|
||||
resp = dict(name=f"{resp_time}_{name}.{ext}", content=html.encode('utf-8'),
|
||||
return dict(name=f"{resp_time}_{name}.{ext}", content=html.encode('utf-8'),
|
||||
mimetype="application/json" if ext == 'json' else "text/html")
|
||||
|
||||
files = [('file', (resp.get('name'), resp.get('content'), resp.get('mimetype'))), ]
|
||||
filename = f'log/{now().strftime("%F")}.log'
|
||||
if os.path.isfile(filename):
|
||||
files.append(('file', (filename[4:], open(filename, 'rb'), 'text/plain')))
|
||||
def _get_local_vars(self) -> str:
|
||||
trace = inspect.trace()
|
||||
local_vars = {}
|
||||
if trace:
|
||||
@ -122,20 +140,46 @@ class ErepublikErrorHTTTPHandler(handlers.HTTPHandler):
|
||||
if local_vars.get('__name__') == '__main__':
|
||||
local_vars.update(commit_id=local_vars.get('COMMIT_ID'), interactive=local_vars.get('INTERACTIVE'),
|
||||
version=local_vars.get('__version__'), config=local_vars.get('CONFIG'))
|
||||
else:
|
||||
stack = inspect.stack()
|
||||
report_error_caller_found = False
|
||||
for frame in stack:
|
||||
if report_error_caller_found:
|
||||
local_vars = frame.frame.f_locals
|
||||
break
|
||||
if 'report_error' in str(frame.frame):
|
||||
report_error_caller_found = True
|
||||
|
||||
if local_vars:
|
||||
if 'state_thread' in local_vars:
|
||||
local_vars.pop('state_thread', None)
|
||||
if 'state_thread' in local_vars:
|
||||
local_vars.pop('state_thread', None)
|
||||
from erepublik import Citizen
|
||||
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'])
|
||||
return json_dumps(local_vars)
|
||||
|
||||
if isinstance(local_vars.get('self'), self.reporter.citizen.__class__):
|
||||
local_vars['self'] = repr(local_vars['self'])
|
||||
if isinstance(local_vars.get('player'), self.reporter.citizen.__class__):
|
||||
local_vars['player'] = repr(local_vars['player'])
|
||||
if isinstance(local_vars.get('citizen'), self.reporter.citizen.__class__):
|
||||
local_vars['citizen'] = repr(local_vars['citizen'])
|
||||
def _get_instance_json(self) -> str:
|
||||
if self.reporter:
|
||||
return self.reporter.citizen.to_json(False)
|
||||
return ""
|
||||
|
||||
files.append(('file', ('local_vars.json', json_dumps(local_vars), "application/json")))
|
||||
files.append(('file', ('instance.json', self.reporter.citizen.to_json(indent=True), "application/json")))
|
||||
def mapLogRecord(self, record: logging.LogRecord) -> Dict[str, Any]:
|
||||
data = super().mapLogRecord(record)
|
||||
|
||||
# Log last response
|
||||
resp = self._get_last_response()
|
||||
files = [('file', (resp.get('name'), resp.get('content'), resp.get('mimetype'))), ]
|
||||
|
||||
files += list(('file', (f, open(f'log/{f}', 'rb'))) for f in os.listdir('log') if f.endswith('.log'))
|
||||
local_vars_json = self._get_local_vars()
|
||||
if local_vars_json:
|
||||
files.append(('file', ('local_vars.json', local_vars_json, "application/json")))
|
||||
instance_json = self._get_instance_json()
|
||||
if instance_json:
|
||||
files.append(('file', ('instance.json', instance_json, "application/json")))
|
||||
data.update(files=files)
|
||||
return data
|
||||
|
@ -1,7 +1,9 @@
|
||||
import datetime
|
||||
import hashlib
|
||||
import random
|
||||
import time
|
||||
from typing import Any, Dict, List, Mapping, Union
|
||||
from requests_toolbelt.utils import dump
|
||||
|
||||
from requests import Response, Session
|
||||
|
||||
@ -45,6 +47,7 @@ class SlowRequests(Session):
|
||||
self.request_log_name = utils.get_file(utils.now().strftime("debug/requests_%Y-%m-%d.log"))
|
||||
self.last_time = utils.now()
|
||||
self.headers.update({'User-Agent': user_agent})
|
||||
self.hooks["response"] = [self._log_response]
|
||||
|
||||
@property
|
||||
def as_dict(self):
|
||||
@ -55,7 +58,7 @@ class SlowRequests(Session):
|
||||
self._slow_down_requests()
|
||||
self._log_request(url, method, **kwargs)
|
||||
resp = super().request(method, url, *args, **kwargs)
|
||||
self._log_response(url, resp)
|
||||
# self._log_response(resp)
|
||||
return resp
|
||||
|
||||
def _slow_down_requests(self):
|
||||
@ -85,12 +88,14 @@ class SlowRequests(Session):
|
||||
with open(self.request_log_name, 'ab') as file:
|
||||
file.write(body.encode("UTF-8"))
|
||||
|
||||
def _log_response(self, url, resp, redirect: bool = False):
|
||||
def _log_response(self, response: Response, *args, **kwargs):
|
||||
redirect = kwargs.get('redirect')
|
||||
url = response.request.url
|
||||
if self.debug:
|
||||
if resp.history and not redirect:
|
||||
for hist_resp in resp.history:
|
||||
if response.history and not redirect:
|
||||
for hist_resp in response.history:
|
||||
self._log_request(hist_resp.request.url, 'REDIRECT')
|
||||
self._log_response(hist_resp.request.url, hist_resp, redirect=True)
|
||||
self._log_response(hist_resp, redirect=True)
|
||||
|
||||
fd_path = 'debug/requests'
|
||||
fd_time = self.last_time.strftime('%Y/%m/%d/%H-%M-%S')
|
||||
@ -98,13 +103,17 @@ class SlowRequests(Session):
|
||||
fd_extra = '_REDIRECT' if redirect else ""
|
||||
|
||||
try:
|
||||
utils.json.loads(resp.text)
|
||||
utils.json.loads(response.text)
|
||||
fd_ext = 'json'
|
||||
except utils.json.JSONDecodeError:
|
||||
fd_ext = 'html'
|
||||
|
||||
filename = f'{fd_path}/{fd_time}_{fd_name}{fd_extra}.{fd_ext}'
|
||||
utils.write_file(filename, resp.text)
|
||||
utils.write_file(filename, response.text)
|
||||
|
||||
if not redirect:
|
||||
data = dump.dump_all(response)
|
||||
utils.write_file(f'debug/dumps/{fd_time}_{fd_name}{fd_extra}.{fd_ext}.dump', data.decode('utf8'))
|
||||
|
||||
|
||||
class CitizenBaseAPI:
|
||||
@ -152,12 +161,27 @@ class CitizenBaseAPI:
|
||||
return self.post(f'{self.url}/main/sessionGetChallenge', data=data)
|
||||
|
||||
def _post_main_session_unlock(
|
||||
self, captcha: int, image: str, challenge: str, coords: List[Dict[str, int]], src: str
|
||||
self, captcha_id: int, image_id: str, challenge_id: str, coords: List[Dict[str, int]], src: str
|
||||
) -> Response:
|
||||
env = dict(l=['tets', ], s=[], c=["l_chathwe", "l_chatroom"], m=0)
|
||||
data = dict(_token=self.token, captchaId=captcha, imageId=image, challengeId=challenge,
|
||||
clickMatrix=coords, isMobile=0, env=utils.b64json(env), src=src)
|
||||
return self.post(f'{self.url}/main/sessionUnlock', data=data)
|
||||
if not self._req.cookies.get('l_chathwe'):
|
||||
self._req.cookies.set('l_chathwe', 1, expires=int(time.time())+300, path="/en/military", domain='.www.erepublik.com', secure=True)
|
||||
if self._req.cookies.get('sh'):
|
||||
self._req.cookies.pop('sh')
|
||||
if self._req.cookies.get('ch'):
|
||||
self._req.cookies.pop('ch')
|
||||
c = [cookie.name for cookie in self._req.cookies if cookie.domain == '.www.erepublik.com' and not cookie.name.startswith('erpk')]
|
||||
env = dict(l=['tets'], s=[], c=c + ['l_chathwe'], m=0)
|
||||
cookies = dict(sh=hashlib.sha256(','.join(env['l']+env['s']).encode('utf8')).hexdigest(),
|
||||
ch=hashlib.sha256(','.join(env['c']).encode('utf8')).hexdigest())
|
||||
cookie_kwargs = dict(expires=int(time.time())+120, path="/en/main/sessionUnlock", domain='.www.erepublik.com',
|
||||
secure=True)
|
||||
self._req.cookies.set('sh', cookies['sh'], **cookie_kwargs)
|
||||
self._req.cookies.set('ch', cookies['ch'], **cookie_kwargs)
|
||||
b64_env = utils.b64json(env)
|
||||
data = dict(_token=self.token, captchaId=captcha_id, imageId=image_id, challengeId=challenge_id,
|
||||
clickMatrix=utils.json_dumps(coords).replace(' ', ''), isMobile=0, env=b64_env, src=src)
|
||||
return self.post(f'{self.url}/main/sessionUnlock', data=data, json=data,
|
||||
headers={'X-Requested-With': 'XMLHttpRequest', 'Referer': 'https://www.erepublik.com/en'})
|
||||
|
||||
|
||||
class ErepublikAnniversaryAPI(CitizenBaseAPI):
|
||||
@ -490,6 +514,10 @@ class ErepublikMilitaryAPI(CitizenBaseAPI):
|
||||
weaponQuality=weapon, totalEnergy=energy, **kwargs)
|
||||
return self.post(f"{self.url}/military/fightDeploy-startDeploy", data=data)
|
||||
|
||||
def _post_military_fight_deploy_deploy_report_data(self, deployment_id: int) -> Response:
|
||||
data = dict(_token=self.token, deploymentId=deployment_id)
|
||||
return self.post(f"{self.url}/military/fightDeploy-deployReportData", data=data)
|
||||
|
||||
|
||||
class ErepublikPoliticsAPI(CitizenBaseAPI):
|
||||
def _get_candidate_party(self, party_slug: str) -> Response:
|
||||
|
@ -9,11 +9,11 @@ from threading import Event
|
||||
from time import sleep
|
||||
from typing import Any, Dict, List, NoReturn, Optional, Set, Tuple, Union
|
||||
|
||||
from requests import HTTPError, RequestException, Response
|
||||
from requests import RequestException, Response, HTTPError
|
||||
|
||||
from . import access_points, classes, constants, types, utils
|
||||
from . import access_points, classes, constants, _types as types, utils
|
||||
from .classes import OfferItem
|
||||
from .logging import ErepublikLogConsoleHandler, ErepublikFormatter, ErepublikFileHandler, ErepublikErrorHTTTPHandler
|
||||
from ._logging import ErepublikErrorHTTTPHandler, ErepublikFileHandler, ErepublikFormatter, ErepublikLogConsoleHandler
|
||||
|
||||
|
||||
class BaseCitizen(access_points.CitizenAPI):
|
||||
@ -93,7 +93,7 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
self.token = re_login_token.group(1)
|
||||
self._login()
|
||||
else:
|
||||
self.logger.error("Something went wrong! Can't find token in page!")
|
||||
self.report_error("Something went wrong! Can't find token in page!")
|
||||
raise classes.ErepublikException("Something went wrong! Can't find token in page! Exiting!")
|
||||
try:
|
||||
self.update_citizen_info(resp.text)
|
||||
@ -111,8 +111,8 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
else:
|
||||
try:
|
||||
response = super().get(url, **kwargs)
|
||||
except RequestException as e:
|
||||
self.logger.error('Network error while issuing GET request', exc_info=e)
|
||||
except RequestException:
|
||||
self.report_error('Network error while issuing GET request')
|
||||
self.sleep(60)
|
||||
return self.get(url, **kwargs)
|
||||
|
||||
@ -144,15 +144,15 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
|
||||
try:
|
||||
response = super().post(url, data=data, json=json, **kwargs)
|
||||
except RequestException as e:
|
||||
self.logger.error('Network error while issuing POST request', exc_info=e)
|
||||
except RequestException:
|
||||
self.report_error('Network error while issuing POST request')
|
||||
self.sleep(60)
|
||||
return self.post(url, data=data, json=json, **kwargs)
|
||||
|
||||
try:
|
||||
r_json = response.json()
|
||||
if (r_json.get('error') or not r_json.get('status')) and r_json.get('message', '') == 'captcha':
|
||||
self.logger.warning('Regular captcha must be filled!', extra=r_json)
|
||||
self.write_warning('Regular captcha must be filled!', extra=r_json)
|
||||
except (AttributeError, utils.json.JSONDecodeError, ValueError, KeyError):
|
||||
pass
|
||||
|
||||
@ -255,16 +255,24 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
data = utils.json_loads(utils.normalize_html_json(data.group(1)))
|
||||
captcha_id = data.get('sessionValidation', {}).get("captchaId")
|
||||
captcha_data = self._post_main_session_get_challenge(captcha_id).json()
|
||||
coordinates = self.solve_captcha(captcha_data.get('src'))
|
||||
r = self._post_main_session_unlock(
|
||||
captcha_id, captcha_data['imageId'], captcha_data['challengeId'], coordinates, captcha_data['src']
|
||||
).json()
|
||||
if not r.get('error') and r.get('verified'):
|
||||
return True
|
||||
else:
|
||||
self.report_error('Captcha failed!')
|
||||
if retry < 6:
|
||||
return self.do_captcha_challenge(retry + 1)
|
||||
coordinates = self.solve_captcha(captcha_data['src'])
|
||||
while True:
|
||||
r = self._post_main_session_unlock(
|
||||
captcha_id, captcha_data['imageId'], captcha_data['challengeId'], coordinates, captcha_data['src']
|
||||
)
|
||||
rj = r.json()
|
||||
if not rj.get('error') and rj.get('verified'):
|
||||
return True
|
||||
else:
|
||||
try:
|
||||
raise classes.ErepublikException('Captcha failed!')
|
||||
except classes.ErepublikException:
|
||||
self.report_error('Captcha failed!')
|
||||
captcha_data = self._post_main_session_get_challenge(captcha_id, captcha_data['imageId']).json()
|
||||
coordinates = self.solve_captcha(captcha_data['src'])
|
||||
if retry < 1:
|
||||
return False
|
||||
retry -= 1
|
||||
return False
|
||||
|
||||
def refresh_captcha_image(self, captcha_id: int, image_id: str):
|
||||
@ -477,11 +485,17 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
def write_log(self, msg: str):
|
||||
self.logger.info(msg)
|
||||
|
||||
def report_error(self, msg: str = "", is_warning: bool = False):
|
||||
if is_warning:
|
||||
self.logger.warning(msg)
|
||||
else:
|
||||
self.logger.error(msg)
|
||||
def write_warning(self, msg: str = "", extra: Dict[str, Any] = None):
|
||||
if extra is None:
|
||||
extra = {}
|
||||
extra.update(erep_version=utils.VERSION)
|
||||
self.logger.warning(msg, extra=extra)
|
||||
|
||||
def report_error(self, msg: str = "", extra: Dict[str, Any] = None):
|
||||
if extra is None:
|
||||
extra = {}
|
||||
extra.update(erep_version=utils.VERSION)
|
||||
self.logger.error(msg, exc_info=True, stack_info=True, extra=extra)
|
||||
|
||||
def sleep(self, seconds: Union[int, float, Decimal]):
|
||||
if seconds < 0:
|
||||
@ -539,9 +553,15 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
|
||||
def dump_instance(self):
|
||||
filename = f"{self.__class__.__name__}__dump.json"
|
||||
cookie_attrs = [
|
||||
"version", "name", "value", "port", "domain", "path", "secure",
|
||||
"expires", "discard", "comment", "comment_url", "rfc2109"
|
||||
]
|
||||
cookies = [{attr: getattr(cookie, attr) for attr in cookie_attrs} for cookie in self._req.cookies]
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
utils.json_dump(dict(config=self.config, cookies=self._req.cookies.get_dict(),
|
||||
user_agent=self._req.headers.get("User-Agent")), f,)
|
||||
utils.json_dump(dict(config=self.config, cookies=cookies,
|
||||
user_agent=self._req.headers.get("User-Agent")), f)
|
||||
self.logger.debug(f"Session saved to: '{filename}'")
|
||||
|
||||
@classmethod
|
||||
@ -549,7 +569,8 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
with open(dump_name) as f:
|
||||
data = utils.json.load(f, object_hook=utils.json_decode_object_hook)
|
||||
player = cls(data['config']['email'], "")
|
||||
player._req.cookies.update(data['cookies'])
|
||||
for cookie in data['cookies']:
|
||||
player._req.cookies.set(**cookie)
|
||||
player._req.headers.update({"User-Agent": data['user_agent']})
|
||||
for k, v in data.get('config', {}).items():
|
||||
if hasattr(player.config, k):
|
||||
@ -568,7 +589,7 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
self.write_log(f"Resumed as: {self.name}")
|
||||
if re.search('<div id="accountSecurity" class="it-hurts-when-ip">', resp.text):
|
||||
self.restricted_ip = True
|
||||
# self.report_error("eRepublik has blacklisted IP. Limited functionality!", True)
|
||||
self.write_warning("eRepublik has blacklisted IP. Limited functionality!")
|
||||
|
||||
self.logged_in = True
|
||||
self.get_csrf_token()
|
||||
@ -774,7 +795,7 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
self.r = r
|
||||
|
||||
if r.url == f"{self.url}/login":
|
||||
self.logger.error("Citizen email and/or password is incorrect!")
|
||||
self.report_error("Citizen email and/or password is incorrect!")
|
||||
else:
|
||||
re_name_id = re.search(r'<a data-fblog="profile_avatar" href="/en/citizen/profile/(\d+)" '
|
||||
r'class="user_avatar" title="(.*?)">', r.text)
|
||||
@ -785,7 +806,7 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
self.get_csrf_token()
|
||||
if re.search('<div id="accountSecurity" class="it-hurts-when-ip">', self.r.text):
|
||||
self.restricted_ip = True
|
||||
# self.report_error('eRepublik has blacklisted IP. Limited functionality!', True)
|
||||
self.write_warning('eRepublik has blacklisted IP. Limited functionality!', )
|
||||
|
||||
self.logged_in = True
|
||||
|
||||
@ -793,7 +814,7 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
try:
|
||||
j = response.json()
|
||||
if j['error'] and j['message'] == 'Too many requests':
|
||||
self.logger.warning('Made too many requests! Sleeping for 30 seconds.')
|
||||
self.write_warning('Made too many requests! Sleeping for 30 seconds.')
|
||||
self.sleep(30)
|
||||
except (utils.json.JSONDecodeError, KeyError, TypeError):
|
||||
pass
|
||||
@ -806,20 +827,20 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
if self.restricted_ip:
|
||||
self._req.cookies.clear()
|
||||
return True
|
||||
self.logger.warning('eRepublik servers are having internal troubles. Sleeping for 5 minutes')
|
||||
self.sleep(5 * 60)
|
||||
self.write_warning('eRepublik servers are having internal troubles. Sleeping for 1 minutes')
|
||||
self.sleep(1 * 60)
|
||||
else:
|
||||
raise classes.ErepublikException(f"HTTP {response.status_code} error!")
|
||||
|
||||
if re.search(r'Occasionally there are a couple of things which we need to check or to implement in order make '
|
||||
r'your experience in eRepublik more pleasant. <strong>Don\'t worry about ongoing battles, timer '
|
||||
r'will be stopped during maintenance.</strong>', response.text):
|
||||
self.logger.warning('eRepublik is having maintenance. Sleeping for 5 mi#nutes')
|
||||
self.write_warning('eRepublik is having maintenance. Sleeping for 5 mi#nutes')
|
||||
self.sleep(5 * 60)
|
||||
return True
|
||||
|
||||
elif re.search('We are experiencing some tehnical dificulties', response.text):
|
||||
self.logger.warning('eRepublik is having technical difficulties. Sleeping for 5 minutes')
|
||||
self.write_warning('eRepublik is having technical difficulties. Sleeping for 5 minutes')
|
||||
self.sleep(5 * 60)
|
||||
return True
|
||||
|
||||
@ -840,7 +861,7 @@ class BaseCitizen(access_points.CitizenAPI):
|
||||
kwargs = utils.json_loads(utils.json_dumps(kwargs or {}))
|
||||
action = action[:32]
|
||||
if msg.startswith('Unable to'):
|
||||
self.logger.warning(msg)
|
||||
self.write_warning(msg)
|
||||
else:
|
||||
self.write_log(msg)
|
||||
if self.reporter.allowed:
|
||||
@ -868,7 +889,7 @@ class CitizenAnniversary(BaseCitizen):
|
||||
|
||||
def spin_wheel_of_fortune(self, max_cost=0, spin_count=0):
|
||||
if not self.config.spin_wheel_of_fortune:
|
||||
self.logger.warning("Unable to spin wheel of fortune because 'config.spin_wheel_of_fortune' is False")
|
||||
self.write_warning("Unable to spin wheel of fortune because 'config.spin_wheel_of_fortune' is False")
|
||||
return
|
||||
|
||||
def _write_spin_data(cost: int, prize: str):
|
||||
@ -1074,7 +1095,7 @@ class CitizenCompanies(BaseCitizen):
|
||||
if wam_list:
|
||||
data.update(extra)
|
||||
if not self.details.current_region == wam_holding.region:
|
||||
self.logger.warning("Unable to work as manager because of location - please travel!")
|
||||
self.write_warning("Unable to work as manager because of location - please travel!")
|
||||
return
|
||||
|
||||
employ_factories = self.my_companies.get_employable_factories()
|
||||
@ -1167,7 +1188,7 @@ class CitizenEconomy(CitizenTravel):
|
||||
if buy is None:
|
||||
pass
|
||||
elif buy['error']:
|
||||
self.logger.warning(f'Unable to buy q{q} house! \n{buy["message"]}')
|
||||
self.write_warning(f'Unable to buy q{q} house! {buy["message"]}')
|
||||
else:
|
||||
ok_to_activate = True
|
||||
else:
|
||||
@ -1273,7 +1294,7 @@ class CitizenEconomy(CitizenTravel):
|
||||
if isinstance(industry, str):
|
||||
industry = constants.INDUSTRIES[industry]
|
||||
if not constants.INDUSTRIES[industry]:
|
||||
self.logger.warning(f"Trying to sell unsupported industry {industry}")
|
||||
self.write_warning(f"Trying to sell unsupported industry {industry}")
|
||||
|
||||
_inv_qlt = quality if industry in [1, 2, 3, 4, 23] else 0
|
||||
final_kind = industry in [1, 2, 4, 23]
|
||||
@ -1328,7 +1349,7 @@ class CitizenEconomy(CitizenTravel):
|
||||
quality = 1
|
||||
product_name = raw_short_names[product_name]
|
||||
elif not constants.INDUSTRIES[product_name]:
|
||||
self.logger.error(f"Industry '{product_name}' not implemented")
|
||||
self.report_error(f"Industry '{product_name}' not implemented")
|
||||
raise classes.ErepublikException(f"Industry '{product_name}' not implemented")
|
||||
|
||||
offers: Dict[str, classes.OfferItem] = {}
|
||||
@ -1385,7 +1406,7 @@ class CitizenEconomy(CitizenTravel):
|
||||
self.update_inventory()
|
||||
else:
|
||||
s = f"Don't have enough money! Needed: {amount * cheapest.price}cc, Have: {self.details.cc}cc"
|
||||
self.logger.warning(s)
|
||||
self.write_warning(s)
|
||||
self._report_action('BUY_FOOD', s)
|
||||
|
||||
def get_monetary_offers(self, currency: int = 62) -> List[Dict[str, Union[int, float]]]:
|
||||
@ -1449,7 +1470,7 @@ class CitizenEconomy(CitizenTravel):
|
||||
self._report_action('DONATE_ITEMS', msg)
|
||||
return amount
|
||||
elif re.search('You must wait 5 seconds before donating again', response.text):
|
||||
self.logger.warning('Previous donation failed! Must wait at least 5 seconds before next donation!')
|
||||
self.write_warning('Previous donation failed! Must wait at least 5 seconds before next donation!')
|
||||
self.sleep(5)
|
||||
return self.donate_items(citizen_id, int(amount), industry_id, quality)
|
||||
else:
|
||||
@ -1601,7 +1622,7 @@ class CitizenMedia(BaseCitizen):
|
||||
kwargs=article_data)
|
||||
self._get_main_delete_article(article_id)
|
||||
else:
|
||||
self.logger.warning(f"Unable to delete article (#{article_id})!")
|
||||
self.write_warning(f"Unable to delete article (#{article_id})!")
|
||||
|
||||
|
||||
class CitizenMilitary(CitizenTravel):
|
||||
@ -1886,7 +1907,7 @@ class CitizenMilitary(CitizenTravel):
|
||||
:rtype: int
|
||||
"""
|
||||
if self.restricted_ip:
|
||||
self.logger.warning('Fighting is not allowed from restricted IP!')
|
||||
self.write_warning('Fighting is not allowed from restricted IP!')
|
||||
self._report_action('IP_BLACKLISTED', 'Fighting is not allowed from restricted IP!')
|
||||
return 1
|
||||
if not division.is_air and self.config.boosters:
|
||||
@ -1894,32 +1915,45 @@ class CitizenMilitary(CitizenTravel):
|
||||
if side is None:
|
||||
side = battle.defender if self.details.citizenship in battle.defender.allies + [
|
||||
battle.defender.country] else battle.invader
|
||||
error_count = 0
|
||||
ok_to_fight = True
|
||||
if count is None:
|
||||
count = self.should_fight()[0]
|
||||
|
||||
self.write_log(f"Fighting in battle for {battle.region_name} on {side} side in d{division.div}")
|
||||
|
||||
total_damage = 0
|
||||
total_hits = 0
|
||||
while ok_to_fight and error_count < 10 and count > 0:
|
||||
while all((count > 0, error_count < 10, self.energy.recovered >= 50)):
|
||||
hits, error, damage = self._shoot(battle, division, side)
|
||||
count -= hits
|
||||
total_hits += hits
|
||||
total_damage += damage
|
||||
error_count += error
|
||||
else:
|
||||
self._eat('blue')
|
||||
if count > 0 and self.energy.recovered < 50 and use_ebs:
|
||||
self._eat('orange')
|
||||
if self.energy.recovered < 50 or error_count >= 10 or count <= 0:
|
||||
self.write_log(f"Hits: {total_hits:>4} | Damage: {total_damage}")
|
||||
ok_to_fight = False
|
||||
if total_damage:
|
||||
self.report_fighting(battle, not side.is_defender, division, total_damage, total_hits)
|
||||
return error_count
|
||||
if self.now < utils.localize_dt(datetime(2021, 2, 8)):
|
||||
error_count = total_damage = total_hits = 0
|
||||
ok_to_fight = True
|
||||
while ok_to_fight and error_count < 10 and count > 0:
|
||||
while all((count > 0, error_count < 10, self.energy.recovered >= 50)):
|
||||
hits, error, damage = self._shoot(battle, division, side)
|
||||
count -= hits
|
||||
total_hits += hits
|
||||
total_damage += damage
|
||||
error_count += error
|
||||
else:
|
||||
self._eat('blue')
|
||||
if count > 0 and self.energy.recovered < 50 and use_ebs:
|
||||
self._eat('orange')
|
||||
if self.energy.recovered < 50 or error_count >= 10 or count <= 0:
|
||||
self.write_log(f"Hits: {total_hits:>4} | Damage: {total_damage}")
|
||||
ok_to_fight = False
|
||||
if total_damage:
|
||||
self.report_fighting(battle, not side.is_defender, division, total_damage, total_hits)
|
||||
return error_count
|
||||
else:
|
||||
deployment_id = self.deploy(division, side, count * 10)
|
||||
self.sleep(count // 3) # TODO: connect to eRepublik's WS and get from there when deploy ends
|
||||
energy_used = 0
|
||||
if deployment_id:
|
||||
self.write_warning('If erepublik responds with HTTP 500 Internal Error, it is kind of ok, because deployment has not finished yet.')
|
||||
deployment_data = self._post_military_fight_deploy_deploy_report_data(deployment_id).json()
|
||||
if not deployment_data.get('error'):
|
||||
data = deployment_data['data']
|
||||
total_damage = int(data['damage'].replace(',', ''))
|
||||
energy_used = int(data['energySpent'].replace(',', ''))
|
||||
self.details.pp += int(data['rewards']['prestigePoints'].replace(',', ''))
|
||||
self.report_fighting(battle, not side.is_defender, division, total_damage, energy_used // 10)
|
||||
return energy_used
|
||||
|
||||
def _shoot(self, battle: classes.Battle, division: classes.BattleDivision, side: classes.BattleSide):
|
||||
if division.is_air:
|
||||
@ -1943,13 +1977,13 @@ class CitizenMilitary(CitizenTravel):
|
||||
elif r_json.get('message') == 'NOT_ENOUGH_WEAPONS':
|
||||
self.set_default_weapon(battle, division)
|
||||
elif r_json.get('message') == "Cannot activate a zone with a non-native division":
|
||||
self.logger.warning('Wrong division!!')
|
||||
self.write_warning('Wrong division!!')
|
||||
return 0, 10, 0
|
||||
elif r_json.get('message') == 'ZONE_INACTIVE':
|
||||
self.logger.warning('Wrong division!!')
|
||||
self.write_warning('Wrong division!!')
|
||||
return 0, 10, 0
|
||||
elif r_json.get('message') == 'NON_BELLIGERENT':
|
||||
self.logger.warning("Dictatorship/Liberation wars are not supported!")
|
||||
self.write_warning("Dictatorship/Liberation wars are not supported!")
|
||||
return 0, 10, 0
|
||||
elif r_json.get('message') in ['FIGHT_DISABLED', 'DEPLOYMENT_MODE']:
|
||||
self._post_main_profile_update('options',
|
||||
@ -2049,7 +2083,7 @@ class CitizenMilitary(CitizenTravel):
|
||||
"""
|
||||
resp = self._post_main_battlefield_change_division(battle.id, division.id, side.id if side else None)
|
||||
if resp.json().get('error'):
|
||||
self.logger.warning(resp.json().get('message'))
|
||||
self.write_warning(resp.json().get('message'))
|
||||
return False
|
||||
self._report_action('MILITARY_DIV_SWITCH', f"Switched to d{division.div} in battle {battle.id}",
|
||||
kwargs=resp.json())
|
||||
@ -2296,11 +2330,16 @@ class CitizenMilitary(CitizenTravel):
|
||||
# self.buy_food()
|
||||
# return self.get_deploy_inventory(division, side)
|
||||
if ret.get('captcha'):
|
||||
while not self.do_captcha_challenge():
|
||||
self.sleep(5)
|
||||
self.do_captcha_challenge()
|
||||
if ret.get('error'):
|
||||
if ret.get('message') == 'Deployment disabled.':
|
||||
self._post_main_profile_update('options', params='{"optionName":"enable_web_deploy","optionValue":"on"}')
|
||||
return self.get_deploy_inventory(division, side)
|
||||
else:
|
||||
self.report_error(f"Unable to get deployment inventory because: {ret.get('message')}")
|
||||
return ret
|
||||
|
||||
def deploy(self, division: classes.BattleDivision, side: classes.BattleSide, energy: int):
|
||||
def deploy(self, division: classes.BattleDivision, side: classes.BattleSide, energy: int, _retry=0) -> int:
|
||||
_energy = int(energy)
|
||||
deploy_inv = self.get_deploy_inventory(division, side)
|
||||
if not deploy_inv['minEnergy'] <= energy <= deploy_inv['maxEnergy']:
|
||||
@ -2312,8 +2351,8 @@ class CitizenMilitary(CitizenTravel):
|
||||
if source['type'] == 'pool':
|
||||
_energy -= source['energy']
|
||||
elif source['type'] in ['food', 'energy_bar']:
|
||||
recovers = source['energy'] / source['amount']
|
||||
amount = recoverable // recovers
|
||||
recovers = source['energy'] // source['amount']
|
||||
amount = (recoverable if source['type'] == 'food' else _energy) // recovers
|
||||
amount = amount if amount < source['amount'] else source['amount']
|
||||
if amount > 0:
|
||||
energy_sources.update({f'energySources[{source_idx}][quality]': source['quality']})
|
||||
@ -2322,7 +2361,10 @@ class CitizenMilitary(CitizenTravel):
|
||||
used_energy = amount * recovers
|
||||
recoverable -= used_energy
|
||||
_energy -= used_energy
|
||||
energy -= _energy
|
||||
if _energy <= 0:
|
||||
break
|
||||
if _energy > 0:
|
||||
energy -= _energy
|
||||
weapon_q = -1
|
||||
weapon_strength = 0
|
||||
if not division.is_air:
|
||||
@ -2332,10 +2374,16 @@ class CitizenMilitary(CitizenTravel):
|
||||
r = self._post_fight_deploy_start_deploy(
|
||||
division.battle.id, side.id, division.id, energy, weapon_q, **energy_sources
|
||||
).json()
|
||||
self.write_log(r.get('message'))
|
||||
if r.get('error'):
|
||||
self.logger.error(f"Deploy failed: '{r.get('message')}'")
|
||||
return energy
|
||||
self.report_error(f"Deploy failed: '{r.get('message')}'")
|
||||
if r.get('message') == 'Deployment disabled.':
|
||||
self._post_main_profile_update('options', params='{"optionName":"enable_web_deploy","optionValue":"on"}')
|
||||
if _retry < 5:
|
||||
return self.deploy(division, side, energy, _retry+1)
|
||||
else:
|
||||
self.report_error('Unable to deploy 5 times!')
|
||||
return 0
|
||||
return r.get('deploymentId')
|
||||
|
||||
|
||||
class CitizenPolitics(BaseCitizen):
|
||||
@ -2408,7 +2456,7 @@ class CitizenSocial(BaseCitizen):
|
||||
def add_every_player_as_friend(self):
|
||||
cities = []
|
||||
cities_dict = {}
|
||||
self.logger.warning('his will take a lot of time.')
|
||||
self.write_warning('This will take a lot of time.')
|
||||
rj = self._post_main_travel_data(regionId=662, check='getCountryRegions').json()
|
||||
for region_data in rj.get('regions', {}).values():
|
||||
cities.append(region_data['cityId'])
|
||||
@ -2519,7 +2567,7 @@ class CitizenTasks(CitizenEconomy):
|
||||
self._eat('blue')
|
||||
if self.energy.food_fights < 1:
|
||||
seconds = (self.energy.reference_time - self.now).total_seconds()
|
||||
self.logger.warning(f"I don't have energy to work. Will sleep for {seconds}s")
|
||||
self.write_warning(f"I don't have energy to work. Will sleep for {seconds}s")
|
||||
self.sleep(seconds)
|
||||
self._eat('blue')
|
||||
self.work()
|
||||
@ -2549,7 +2597,7 @@ class CitizenTasks(CitizenEconomy):
|
||||
if self.energy.food_fights < len(tgs):
|
||||
large = max(self.energy.reference_time, self.now)
|
||||
sleep_seconds = utils.get_sleep_seconds(large)
|
||||
self.logger.warning(f"I don't have energy to train. Will sleep for {sleep_seconds} seconds")
|
||||
self.write_warning(f"I don't have energy to train. Will sleep for {sleep_seconds} seconds")
|
||||
self.sleep(sleep_seconds)
|
||||
self._eat('blue')
|
||||
self.train()
|
||||
@ -2573,7 +2621,7 @@ class CitizenTasks(CitizenEconomy):
|
||||
if self.energy.food_fights < 1:
|
||||
large = max(self.energy.reference_time, self.now)
|
||||
sleep_seconds = utils.get_sleep_seconds(large)
|
||||
self.logger.warning(f"I don't have energy to work OT. Will sleep for {sleep_seconds}s")
|
||||
self.write_warning(f"I don't have energy to work OT. Will sleep for {sleep_seconds}s")
|
||||
self.sleep(sleep_seconds)
|
||||
self._eat('blue')
|
||||
self.work_ot()
|
||||
@ -2653,7 +2701,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
if hasattr(self.config, key):
|
||||
setattr(self.config, key, value)
|
||||
else:
|
||||
self.logger.warning(f"Unknown config parameter! ({key}={value})")
|
||||
self.write_warning(f"Unknown config parameter! ({key}={value})")
|
||||
|
||||
def login(self):
|
||||
self.get_csrf_token()
|
||||
@ -2666,12 +2714,8 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
self.name)
|
||||
self.telegram.send_message(f"*Started* {utils.now():%F %T}")
|
||||
|
||||
self.init_logger()
|
||||
self.update_all(True)
|
||||
for handler in self.logger.handlers:
|
||||
if isinstance(handler, ErepublikErrorHTTTPHandler):
|
||||
self.logger.removeHandler(handler)
|
||||
break
|
||||
self.logger.addHandler(ErepublikErrorHTTTPHandler(self.reporter))
|
||||
|
||||
def update_citizen_info(self, html: str = None):
|
||||
"""
|
||||
@ -2689,7 +2733,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
if self.details.gold >= 54:
|
||||
self.buy_tg_contract()
|
||||
else:
|
||||
self.logger.warning('Training ground contract active but '
|
||||
self.write_warning('Training ground contract active but '
|
||||
f"don't have enough gold ({self.details.gold}g {self.details.cc}cc)")
|
||||
if self.energy.is_energy_full and self.config.telegram:
|
||||
self.telegram.report_full_energy(self.energy.available, self.energy.limit, self.energy.interval)
|
||||
@ -2849,15 +2893,15 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
else:
|
||||
self.logger.debug("I don't want to eat right now!")
|
||||
else:
|
||||
self.logger.warning(f"I'm out of food! But I'll try to buy some!\n{self.food}")
|
||||
self.write_warning(f"I'm out of food! But I'll try to buy some!\n{self.food}")
|
||||
self.buy_food()
|
||||
if self.food['total'] > self.energy.interval:
|
||||
super().eat()
|
||||
else:
|
||||
self.logger.warning('I failed to buy food')
|
||||
self.write_warning('I failed to buy food')
|
||||
|
||||
def eat_eb(self):
|
||||
self.logger.warning('Eating energy bar')
|
||||
self.write_warning('Eating energy bar')
|
||||
if self.energy.recoverable:
|
||||
self._eat('blue')
|
||||
self._eat('orange')
|
||||
@ -2921,7 +2965,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
if not rj.get('error'):
|
||||
amount_needed -= amount
|
||||
else:
|
||||
self.logger.warning(rj.get('message', ""))
|
||||
self.write_warning(rj.get('message', ""))
|
||||
self._report_action(
|
||||
'ECONOMY_BUY', f"Unable to buy products! Reason: {rj.get('message')}", kwargs=rj
|
||||
)
|
||||
@ -2940,11 +2984,11 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
self._wam(holding)
|
||||
elif response.get('message') == 'tax_money':
|
||||
self._report_action('WORK_AS_MANAGER', 'Not enough money to work as manager!', kwargs=response)
|
||||
self.logger.warning('Not enough money to work as manager!')
|
||||
self.write_warning('Not enough money to work as manager!')
|
||||
else:
|
||||
msg = f'I was not able to wam and or employ because:\n{response}'
|
||||
self._report_action('WORK_AS_MANAGER', f'Worked as manager failed: {msg}', kwargs=response)
|
||||
self.logger.warning(msg)
|
||||
self.write_warning(msg)
|
||||
|
||||
def work_as_manager(self) -> bool:
|
||||
""" Does Work as Manager in all holdings with wam. If employees assigned - work them also
|
||||
@ -2986,7 +3030,7 @@ class _Citizen(CitizenAnniversary, CitizenCompanies, CitizenLeaderBoard,
|
||||
self.travel_to_residence()
|
||||
return bool(wam_count)
|
||||
else:
|
||||
self.logger.warning('Did not WAM because I would mess up levelup!')
|
||||
self.write_warning('Did not WAM because I would mess up levelup!')
|
||||
self.my_companies.ff_lockdown = 0
|
||||
|
||||
self.update_companies()
|
||||
@ -3028,7 +3072,7 @@ class Citizen(_Citizen):
|
||||
def update_weekly_challenge(self):
|
||||
if not self._update_lock.wait(self._update_timeout):
|
||||
e = f'Update concurrency not freed in {self._update_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._update_lock.clear()
|
||||
@ -3039,7 +3083,7 @@ class Citizen(_Citizen):
|
||||
def update_companies(self):
|
||||
if not self._update_lock.wait(self._update_timeout):
|
||||
e = f'Update concurrency not freed in {self._update_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._update_lock.clear()
|
||||
@ -3050,7 +3094,7 @@ class Citizen(_Citizen):
|
||||
def update_war_info(self):
|
||||
if not self._update_lock.wait(self._update_timeout):
|
||||
e = f'Update concurrency not freed in {self._update_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._update_lock.clear()
|
||||
@ -3061,7 +3105,7 @@ class Citizen(_Citizen):
|
||||
def update_job_info(self):
|
||||
if not self._update_lock.wait(self._update_timeout):
|
||||
e = f'Update concurrency not freed in {self._update_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._update_lock.clear()
|
||||
@ -3072,7 +3116,7 @@ class Citizen(_Citizen):
|
||||
def update_money(self, page: int = 0, currency: int = 62):
|
||||
if not self._update_lock.wait(self._update_timeout):
|
||||
e = f'Update concurrency not freed in {self._update_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._update_lock.clear()
|
||||
@ -3083,7 +3127,7 @@ class Citizen(_Citizen):
|
||||
def update_inventory(self):
|
||||
if not self._update_lock.wait(self._update_timeout):
|
||||
e = f'Update concurrency not freed in {self._update_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._update_lock.clear()
|
||||
@ -3094,7 +3138,7 @@ class Citizen(_Citizen):
|
||||
def _work_as_manager(self, wam_holding: classes.Holding) -> Optional[Dict[str, Any]]:
|
||||
if not self._concurrency_lock.wait(self._concurrency_timeout):
|
||||
e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._concurrency_lock.clear()
|
||||
@ -3106,7 +3150,7 @@ class Citizen(_Citizen):
|
||||
count: int = None, use_ebs: bool = False) -> Optional[int]:
|
||||
if not self._concurrency_lock.wait(self._concurrency_timeout):
|
||||
e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._concurrency_lock.clear()
|
||||
@ -3118,7 +3162,7 @@ class Citizen(_Citizen):
|
||||
count: int = 1) -> Optional[int]:
|
||||
if not self._concurrency_lock.wait(self._concurrency_timeout):
|
||||
e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._concurrency_lock.clear()
|
||||
@ -3129,7 +3173,7 @@ class Citizen(_Citizen):
|
||||
def buy_market_offer(self, offer: OfferItem, amount: int = None) -> Optional[Dict[str, Any]]:
|
||||
if not self._concurrency_lock.wait(self._concurrency_timeout):
|
||||
e = f'Concurrency not freed in {self._concurrency_timeout}sec!'
|
||||
self.report_error(e, not self.debug)
|
||||
self.report_error(e)
|
||||
return None
|
||||
try:
|
||||
self._concurrency_lock.clear()
|
||||
|
@ -7,7 +7,7 @@ from typing import Any, Dict, Generator, Iterable, List, NamedTuple, NoReturn, U
|
||||
|
||||
from requests import Response, Session, post
|
||||
|
||||
from . import constants, types, utils
|
||||
from . import constants, _types as types, utils
|
||||
|
||||
__all__ = ['Battle', 'BattleDivision', 'BattleSide', 'Company', 'Config', 'Details', 'Energy', 'ErepublikException',
|
||||
'ErepublikNetworkException', 'EnergyToFight', 'Holding', 'Inventory', 'MyCompanies', 'OfferItem', 'Politics',
|
||||
|
@ -296,7 +296,7 @@ def json_dumps(obj, *args, **kwargs):
|
||||
|
||||
def b64json(obj: Union[Dict[str, Union[int, List[str]]], List[str]]):
|
||||
if isinstance(obj, list):
|
||||
return b64encode(json.dumps(obj).encode('utf-8')).decode('utf-8')
|
||||
return b64encode(json.dumps(obj).replace(' ', '').encode('utf-8')).decode('utf-8')
|
||||
elif isinstance(obj, (int, str)):
|
||||
return obj
|
||||
elif isinstance(obj, dict):
|
||||
@ -305,7 +305,7 @@ def b64json(obj: Union[Dict[str, Union[int, List[str]]], List[str]]):
|
||||
else:
|
||||
from .classes import ErepublikException
|
||||
raise ErepublikException(f'Unhandled object type! obj is {type(obj)}')
|
||||
return b64encode(json.dumps(obj).encode('utf-8')).decode('utf-8')
|
||||
return b64encode(json.dumps(obj).replace(' ', '').encode('utf-8')).decode('utf-8')
|
||||
|
||||
|
||||
class ErepublikJSONEncoder(json.JSONEncoder):
|
||||
|
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.24.0.5
|
||||
current_version = 0.24.1
|
||||
commit = True
|
||||
tag = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\.?(?P<dev>\d+)?
|
||||
|
Reference in New Issue
Block a user