Citizen.set_default_weapon() - eRepublik should return list with all available weapon qualities, but when a battle is just launched, they return only dict with barehands
Citizen.fight() - no longer calls self.set_default_weapon()
Citizen.find_battle_and_fight() - now calls self.set_default_weapon() just before fighting
Citizen.update_war_info() - returns previous battle list if responses 'last_updated' isn't more than 30s old

New:
Citizen.get_battle_for_war(war_id) - returns Battle instance for specific war, if battle is active for given war
This commit is contained in:
Eriks Karls 2020-01-13 10:28:42 +02:00
parent 1c47d169d2
commit 1f07f2e270
2 changed files with 36 additions and 28 deletions

View File

@ -1,20 +1,20 @@
import json
import re import re
import sys import sys
import warnings
from collections import defaultdict
from datetime import datetime, timedelta from datetime import datetime, timedelta
from itertools import product from itertools import product
from json import loads, dumps from json import dumps, loads
from threading import Event from threading import Event
from time import sleep from time import sleep
from typing import Dict, List, Tuple, Any, Union, Set from typing import Any, Dict, List, Optional, Set, Tuple, Union
from requests import Response, RequestException from requests import RequestException, Response
from erepublik.classes import (CitizenAPI, Battle, Reporter, Config, Energy, Details, Politics, MyCompanies, from erepublik.classes import (Battle, BattleDivision, CitizenAPI, Config,
TelegramBot, ErepublikException, BattleDivision, MyJSONEncoder) Details, Energy, ErepublikException,
MyCompanies, MyJSONEncoder, Politics, Reporter,
TelegramBot)
from erepublik.utils import * from erepublik.utils import *
from erepublik.utils import process_warning
class Citizen(CitizenAPI): class Citizen(CitizenAPI):
@ -112,6 +112,9 @@ class Citizen(CitizenAPI):
def __str__(self) -> str: def __str__(self) -> str:
return f"Citizen {self.name}" return f"Citizen {self.name}"
def __repr__(self):
return self.__str__()
def __dict__(self): def __dict__(self):
ret = super().__dict__.copy() ret = super().__dict__.copy()
ret.pop('stop_threads', None) ret.pop('stop_threads', None)
@ -178,7 +181,7 @@ class Citizen(CitizenAPI):
if j['error'] and j["message"] == 'Too many requests': if j['error'] and j["message"] == 'Too many requests':
self.write_log("Made too many requests! Sleeping for 30 seconds.") self.write_log("Made too many requests! Sleeping for 30 seconds.")
self.sleep(30) self.sleep(30)
except: except (json.JSONDecodeError, KeyError, TypeError):
pass pass
if response.status_code >= 400: if response.status_code >= 400:
self.r = response self.r = response
@ -559,10 +562,13 @@ class Citizen(CitizenAPI):
if not self.details.current_country: if not self.details.current_country:
self.update_citizen_info() self.update_citizen_info()
resp_json = self._get_military_campaigns_json_list().json() if self.__last_war_update_data and self.__last_war_update_data.get('last_updated', 0) + 30 > self.now.timestamp():
resp_json = self.__last_war_update_data
else:
resp_json = self._get_military_campaigns_json_list().json()
if resp_json.get("countries"): if resp_json.get("countries"):
if self.all_battles is None: if self.all_battles is None:
self.all_battles = defaultdict(Battle) self.all_battles = {}
else: else:
self.all_battles.clear() self.all_battles.clear()
@ -638,7 +644,7 @@ class Citizen(CitizenAPI):
def now(self) -> datetime: def now(self) -> datetime:
""" """
Returns aware datetime object localized to US/Pacific (eRepublik time) Returns aware datetime object localized to US/Pacific (eRepublik time)
:return: datetime.datetime :return: datetime
""" """
return now() return now()
@ -811,6 +817,7 @@ class Citizen(CitizenAPI):
if not self.travel_to_battle(battle_id, country_ids_to_travel): if not self.travel_to_battle(battle_id, country_ids_to_travel):
break break
self.set_default_weapon(battle_id)
self.fight(battle_id, side_id) self.fight(battle_id, side_id)
self.travel_to_residence() self.travel_to_residence()
self.collect_weekly_reward() self.collect_weekly_reward()
@ -819,8 +826,7 @@ class Citizen(CitizenAPI):
def fight(self, battle_id: int, side_id: int = None, count: int = None) -> int: def fight(self, battle_id: int, side_id: int = None, count: int = None) -> int:
"""Fight in a battle. """Fight in a battle.
Will auto activate booster and travel if allowed to do it and Will auto activate booster and travel if allowed to do it.
in the beginning will switch to default weapon (air - bare hands, ground - q7, if count > 30, else bare hands.
:param battle_id: int BattleId - battle to fight in :param battle_id: int BattleId - battle to fight in
:param side_id: int or None. Battle side to fight in, If side_id not == invader id or not in invader deployed allies list, then defender's side is chosen :param side_id: int or None. Battle side to fight in, If side_id not == invader id or not in invader deployed allies list, then defender's side is chosen
:param count: How many hits to do, if not specified self.should_fight() is called. :param count: How many hits to do, if not specified self.should_fight() is called.
@ -831,11 +837,10 @@ class Citizen(CitizenAPI):
battle_id = int(battle_id) battle_id = int(battle_id)
if battle_id not in self.all_battles: if battle_id not in self.all_battles:
self.update_war_info() self.update_war_info()
battle = self.all_battles[battle_id] battle = self.all_battles.get(battle_id)
zone_id = battle.div[11 if battle.is_air else self.division].battle_zone_id zone_id = battle.div[11 if battle.is_air else self.division].battle_zone_id
if not battle.is_air and self.config.boosters: if not battle.is_air and self.config.boosters:
self.activate_dmg_booster() self.activate_dmg_booster()
self.set_default_weapon(battle_id)
error_count = 0 error_count = 0
ok_to_fight = True ok_to_fight = True
if count is None: if count is None:
@ -862,7 +867,7 @@ class Citizen(CitizenAPI):
return error_count return error_count
def _shoot(self, battle_id: int, inv_side: bool, zone_id: int): def _shoot(self, battle_id: int, inv_side: bool, zone_id: int):
battle = self.all_battles[battle_id] battle = self.all_battles.get(battle_id)
side_id = battle.invader.id if inv_side else battle.defender.id side_id = battle.invader.id if inv_side else battle.defender.id
if battle.is_air: if battle.is_air:
response = self._post_military_fight_air(battle_id, side_id, zone_id) response = self._post_military_fight_air(battle_id, side_id, zone_id)
@ -914,7 +919,7 @@ class Citizen(CitizenAPI):
if not isinstance(count, int) or count < 1: if not isinstance(count, int) or count < 1:
count = 1 count = 1
has_traveled = False has_traveled = False
battle = self.all_battles[battle_id] battle = self.all_battles.get(battle_id)
if inv_side: if inv_side:
good_countries = [battle.invader.id] + battle.invader.deployed good_countries = [battle.invader.id] + battle.invader.deployed
if self.details.current_country not in good_countries: if self.details.current_country not in good_countries:
@ -946,7 +951,7 @@ class Citizen(CitizenAPI):
:param division_to: int target division to switch to :param division_to: int target division to switch to
:return: :return:
""" """
battle = self.all_battles[battle_id] battle = self.all_battles.get(battle_id)
self._post_main_battlefield_change_division(battle_id, battle.div[division_to].battle_zone_id) self._post_main_battlefield_change_division(battle_id, battle.div[division_to].battle_zone_id)
def work_ot(self): def work_ot(self):
@ -2136,8 +2141,10 @@ class Citizen(CitizenAPI):
return self._get_military_show_weapons(battle_id).json() return self._get_military_show_weapons(battle_id).json()
def set_default_weapon(self, battle_id: int) -> int: def set_default_weapon(self, battle_id: int) -> int:
battle = self.all_battles[battle_id] battle = self.all_battles.get(battle_id)
available_weapons = self._get_military_show_weapons(battle_id).json() available_weapons = self._get_military_show_weapons(battle_id).json()
while not isinstance(available_weapons, list):
available_weapons = self._get_military_show_weapons(battle_id).json()
weapon_quality = -1 weapon_quality = -1
if not battle.is_air: if not battle.is_air:
for weapon in available_weapons: for weapon in available_weapons:
@ -2147,7 +2154,12 @@ class Citizen(CitizenAPI):
return self.change_weapon(battle_id, weapon_quality) return self.change_weapon(battle_id, weapon_quality)
def change_weapon(self, battle_id: int, weapon_quality: int) -> int: def change_weapon(self, battle_id: int, weapon_quality: int) -> int:
battle = self.all_battles[battle_id] battle = self.all_battles.get(battle_id)
battle_zone = battle.div[11 if battle.is_air else self.division].battle_zone_id battle_zone = battle.div[11 if battle.is_air else self.division].battle_zone_id
r = self._post_military_change_weapon(battle_id, battle_zone, weapon_quality) r = self._post_military_change_weapon(battle_id, battle_zone, weapon_quality)
return r.json().get('weaponInfluence') return r.json().get('weaponInfluence')
def get_battle_for_war(self, war_id: int) -> Optional[Battle]:
self.update_war_info()
war_info = self.get_war_status(war_id)
return self.all_battles.get(war_info.get("battle_id"), None)

View File

@ -4,9 +4,9 @@ import hashlib
import random import random
import threading import threading
import time import time
from collections import deque, defaultdict from collections import defaultdict, deque
from json import JSONDecodeError, loads, JSONEncoder from json import JSONDecodeError, JSONEncoder, loads
from typing import Any, Dict, List, Union, Mapping, Iterable, Tuple from typing import Any, Dict, Iterable, List, Mapping, Tuple, Union
from requests import Response, Session, post from requests import Response, Session, post
@ -567,10 +567,6 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
def _get_military_campaigns_json_list(self) -> Response: def _get_military_campaigns_json_list(self) -> Response:
return self.get("{}/military/campaignsJson/list".format(self.url)) return self.get("{}/military/campaignsJson/list".format(self.url))
def _get_military_show_weapons(self, battle_id: int) -> Response:
params = {"_token": self.token, "battleId": battle_id}
return self.get("{}/military/show-weapons".format(self.url), params=params)
def _get_military_unit_data(self, unit_id: int, **kwargs) -> Response: def _get_military_unit_data(self, unit_id: int, **kwargs) -> Response:
params = {"groupId": unit_id, "panel": "members", **kwargs} params = {"groupId": unit_id, "panel": "members", **kwargs}
return self.get("{}/military/military-unit-data/".format(self.url), params=params) return self.get("{}/military/military-unit-data/".format(self.url), params=params)