@ -2,9 +2,8 @@ import datetime
import decimal
import decimal
import hashlib
import hashlib
import random
import random
import sys
import threading
import time
import time
import traceback
from collections import deque
from collections import deque
from json import JSONDecodeError , loads , JSONEncoder
from json import JSONDecodeError , loads , JSONEncoder
from typing import Any , Dict , List , Union , Mapping , Iterable , Tuple
from typing import Any , Dict , List , Union , Mapping , Iterable , Tuple
@ -19,7 +18,7 @@ class ErepublikException(Exception):
super ( ) . __init__ ( message )
super ( ) . __init__ ( message )
class ErepublikNetworkException ( Exception) :
class ErepublikNetworkException ( Erepublik Exception) :
def __init__ ( self , message , request ) :
def __init__ ( self , message , request ) :
super ( ) . __init__ ( message )
super ( ) . __init__ ( message )
self . request = request
self . request = request
@ -161,13 +160,13 @@ class MyCompanies:
raise ErepublikException ( " Wrong function call " )
raise ErepublikException ( " Wrong function call " )
@property
# @property
def __dict__( self ) :
# def __dict__(self) :
ret = { }
# ret = { }
for key in dir ( self ) :
# for key in dir(self) :
if not key . startswith ( ' _ ' ) :
# if not key.startswith('_') :
ret[ key ] = getattr ( self , key )
# ret[key] = getattr(self, key)
return ret
# return ret
class SlowRequests ( Session ) :
class SlowRequests ( Session ) :
@ -202,7 +201,7 @@ class SlowRequests(Session):
@property
@property
def __dict__ ( self ) :
def __dict__ ( self ) :
return dict ( last_time = self . last_time , timeout = self . timeout , user_agent = self . headers [ ' User-Agent ' ] ,
return dict ( last_time = self . last_time , timeout = self . timeout , user_agent = self . headers [ ' User-Agent ' ] ,
request_log_name = self . request_log_name )
request_log_name = self . request_log_name , debug = self . debug )
def request ( self , method , url , * args , * * kwargs ) :
def request ( self , method , url , * args , * * kwargs ) :
self . _slow_down_requests ( )
self . _slow_down_requests ( )
@ -221,7 +220,10 @@ class SlowRequests(Session):
def _log_request ( self , url , method , data = None , json = None , params = None , * * kwargs ) :
def _log_request ( self , url , method , data = None , json = None , params = None , * * kwargs ) :
if self . debug :
if self . debug :
args = { }
args = { }
args . update ( { ' kwarg s' : kwargs } )
kw args. pop ( ' allow_redirect s' , None )
if kwargs :
args . update ( { ' kwargs ' : kwargs } )
if data :
if data :
args . update ( { " data " : data } )
args . update ( { " data " : data } )
@ -245,10 +247,9 @@ class SlowRequests(Session):
self . _log_request ( hist_resp . request . url , " REDIRECT " )
self . _log_request ( hist_resp . request . url , " REDIRECT " )
self . _log_response ( hist_resp . request . url , hist_resp , redirect = True )
self . _log_response ( hist_resp . request . url , hist_resp , redirect = True )
# TODO: Must thoroughly check response writing on windows systems
file_data = {
file_data = {
" path " : ' debug/requests ' ,
" path " : ' debug/requests ' ,
" time " : self . last_time . strftime ( ' % Y- % m- %d _ % H- % M- % S ' ) ,
" time " : self . last_time . strftime ( ' % Y/ % m/ %d / % H- % M- % S ' ) ,
" name " : utils . slugify ( url [ len ( Citizen . url ) : ] ) ,
" name " : utils . slugify ( url [ len ( Citizen . url ) : ] ) ,
" extra " : " _REDIRECT " if redirect else " "
" extra " : " _REDIRECT " if redirect else " "
}
}
@ -270,7 +271,7 @@ class Config:
work = True
work = True
train = True
train = True
wam = False
wam = False
auto_sell : List [ str ] = list ( )
auto_sell : List [ str ] = None
auto_sell_all = False
auto_sell_all = False
employees = False
employees = False
fight = False
fight = False
@ -294,17 +295,40 @@ class Config:
telegram_chat_id = 0
telegram_chat_id = 0
telegram_token = " "
telegram_token = " "
def __init__ ( self ) :
self . auto_sell = [ ]
@property
@property
def wt ( self ) :
def wt ( self ) :
return self . work and self . train
return self . work and self . train
@property
def reset ( self ) :
def __dict__ ( self ) - > Dict [ str , Union [ bool , str , List [ str ] ] ] :
self . work = True
ret = { }
self . train = True
for key in dir ( self ) :
self . wam = False
if not key . startswith ( ' _ ' ) and key not in [ ' email ' , ' password ' ] :
self . auto_sell = list ( )
ret [ key ] = getattr ( self , key )
self . auto_sell_all = False
return ret
self . employees = False
self . fight = False
self . air = False
self . ground = False
self . all_in = False
self . next_energy = False
self . boosters = False
self . travel_to_fight = False
self . always_travel = False
self . epic_hunt = False
self . epic_hunt_ebs = False
self . rw_def_side = False
self . interactive = True
self . continuous_fighting = False
self . auto_buy_raw = False
self . force_wam = False
self . sort_battles_time = True
self . force_travel = False
self . telegram = True
self . telegram_chat_id = 0
self . telegram_token = " "
class Energy :
class Energy :
@ -351,22 +375,14 @@ class Energy:
def available ( self ) :
def available ( self ) :
return self . recovered + self . recoverable
return self . recovered + self . recoverable
@property
def __dict__ ( self ) :
ret = { }
for key in dir ( self ) :
if not key . startswith ( ' _ ' ) :
ret [ key ] = getattr ( self , key )
return ret
class Details :
class Details ( object ) :
xp = 0
xp = 0
cc = 0
cc = 0
pp = 0
pp = 0
pin = None
pin = None
gold = 0
gold = 0
next_pp : List [ int ] = [ ]
next_pp : List [ int ] = None
citizen_id = 0
citizen_id = 0
citizenship = 0
citizenship = 0
current_region = 0
current_region = 0
@ -377,6 +393,9 @@ class Details(object):
daily_task_reward = False
daily_task_reward = False
mayhem_skills = { 1 : 0 , 2 : 0 , 3 : 0 , 4 : 0 , 5 : 0 , 6 : 0 , 7 : 0 , 8 : 0 , 9 : 0 , 10 : 0 , 11 : 0 , 12 : 0 , 13 : 0 , 14 : 0 , }
mayhem_skills = { 1 : 0 , 2 : 0 , 3 : 0 , 4 : 0 , 5 : 0 , 6 : 0 , 7 : 0 , 8 : 0 , 9 : 0 , 10 : 0 , 11 : 0 , 12 : 0 , 13 : 0 , 14 : 0 , }
def __init__ ( self ) :
self . next_pp = [ ]
@property
@property
def xp_till_level_up ( self ) :
def xp_till_level_up ( self ) :
if self . xp > = 10000 :
if self . xp > = 10000 :
@ -403,14 +422,6 @@ class Details(object):
next_level_up = ( 1 + ( self . xp / / 10 ) ) * 10
next_level_up = ( 1 + ( self . xp / / 10 ) ) * 10
return next_level_up - self . xp
return next_level_up - self . xp
@property
def __dict__ ( self ) :
ret = { }
for key in dir ( self ) :
if not key . startswith ( ' _ ' ) :
ret [ key ] = getattr ( self , key )
return ret
class Politics :
class Politics :
is_party_member : bool = False
is_party_member : bool = False
@ -421,16 +432,8 @@ class Politics:
is_congressman : bool = False
is_congressman : bool = False
is_country_president : bool = False
is_country_president : bool = False
@property
def __dict__ ( self ) :
ret = { }
for key in dir ( self ) :
if not key . startswith ( ' _ ' ) :
ret [ key ] = getattr ( self , key )
return ret
class House :
class House ( object ) :
quality = None
quality = None
unactivated_count = 0
unactivated_count = 0
active_untill = utils . good_timedelta ( utils . now ( ) , - datetime . timedelta ( days = 1 ) )
active_untill = utils . good_timedelta ( utils . now ( ) , - datetime . timedelta ( days = 1 ) )
@ -455,8 +458,8 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
"""
"""
self . _req = SlowRequests ( )
self . _req = SlowRequests ( )
def post ( self , url : str , * args , * * kwargs ) - > Response :
def post ( self , url : str , data = None , json = None , * * kwargs ) - > Response :
return self . _req . post ( url , * args , * * kwargs )
return self . _req . post ( url , data , json , * * kwargs )
def get ( self , url : str , * * kwargs ) - > Response :
def get ( self , url : str , * * kwargs ) - > Response :
return self . _req . get ( url , * * kwargs )
return self . _req . get ( url , * * kwargs )
@ -467,6 +470,9 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
def _get_military_battlefield_choose_side ( self , battle : int , side : int ) - > Response :
def _get_military_battlefield_choose_side ( self , battle : int , side : int ) - > Response :
return self . get ( " {} /military/battlefield-choose-side/ {} / {} " . format ( self . url , battle , side ) )
return self . get ( " {} /military/battlefield-choose-side/ {} / {} " . format ( self . url , battle , side ) )
def _get_military_show_weapons ( self , battle : int ) - > Response :
return self . get ( " {} /military/show-weapons " . format ( self . url ) , params = { ' _token ' : self . token , ' battleId ' : battle } )
def _get_candidate_party ( self , party_slug : str ) - > Response :
def _get_candidate_party ( self , party_slug : str ) - > Response :
return self . post ( " {} /candidate/ {} " . format ( self . url , party_slug ) )
return self . post ( " {} /candidate/ {} " . format ( self . url , party_slug ) )
@ -532,6 +538,9 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
def _get_military_campaigns ( self ) - > Response :
def _get_military_campaigns ( self ) - > Response :
return self . get ( " {} /military/campaigns-new/ " . format ( self . url ) )
return self . get ( " {} /military/campaigns-new/ " . format ( self . url ) )
def _get_military_campaigns_json_list ( self ) - > Response :
return self . get ( " {} /military/campaignsJson/list " . format ( self . url ) )
def _get_military_show_weapons ( self , battle_id : int ) - > Response :
def _get_military_show_weapons ( self , battle_id : int ) - > Response :
params = { " _token " : self . token , " battleId " : battle_id }
params = { " _token " : self . token , " battleId " : battle_id }
return self . get ( " {} /military/show-weapons " . format ( self . url ) , params = params )
return self . get ( " {} /military/show-weapons " . format ( self . url ) , params = params )
@ -590,6 +599,10 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
data = dict ( _token = self . token , sideCountryId = side_id , battleId = battle_id )
data = dict ( _token = self . token , sideCountryId = side_id , battleId = battle_id )
return self . post ( " {} /main/battlefieldTravel " . format ( self . url ) , data = data )
return self . post ( " {} /main/battlefieldTravel " . format ( self . url ) , data = data )
def _post_main_battlefield_change_division ( self , battle_id : int , division_id : int ) - > Response :
data = dict ( _token = self . token , battleZoneId = division_id , battleId = battle_id )
return self . post ( " {} /main/battlefieldTravel " . format ( self . url ) , data = data )
def _post_main_buy_gold_items ( self , currency : str , item : str , amount : int ) - > Response :
def _post_main_buy_gold_items ( self , currency : str , item : str , amount : int ) - > Response :
data = dict ( itemId = item , currency = currency , amount = amount , _token = self . token )
data = dict ( itemId = item , currency = currency , amount = amount , _token = self . token )
return self . post ( " {} /main/buyGoldItems " . format ( self . url ) , data = data )
return self . post ( " {} /main/buyGoldItems " . format ( self . url ) , data = data )
@ -760,6 +773,10 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
data = dict ( type = kind , quality = quality , duration = duration , battleId = battle , _token = self . token )
data = dict ( type = kind , quality = quality , duration = duration , battleId = battle , _token = self . token )
return self . post ( " {} /military/fight-activateBooster " . format ( self . url ) , data = data )
return self . post ( " {} /military/fight-activateBooster " . format ( self . url ) , data = data )
def _post_military_change_weapon ( self , battle : int , battle_zone : int , weapon_level : int , ) - > Response :
data = dict ( battleId = battle , _token = self . token , battleZoneId = battle_zone , customizationLevel = weapon_level )
return self . post ( " {} /military/change-weapon " . format ( self . url ) , data = data )
def _post_login ( self , email : str , password : str ) - > Response :
def _post_login ( self , email : str , password : str ) - > Response :
data = dict ( csrf_token = self . token , citizen_email = email , citizen_password = password , remember = ' on ' )
data = dict ( csrf_token = self . token , citizen_email = email , citizen_password = password , remember = ' on ' )
return self . post ( " {} /login " . format ( self . url ) , data = data )
return self . post ( " {} /login " . format ( self . url ) , data = data )
@ -783,21 +800,16 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
data . update ( page = page )
data . update ( page = page )
return self . post ( " {} /military/battle-console " . format ( self . url ) , data = data )
return self . post ( " {} /military/battle-console " . format ( self . url ) , data = data )
def _post_military_change_weapon ( self , battle_id : int , battle_zone_id : int , customization_level : int ) - > Response :
data = dict ( _token = self . token , battleZoneId = battle_zone_id , battleId = battle_id ,
customizationLevel = customization_level )
return self . post ( " {} /military/change-weapon " . format ( self . url ) , data = data )
def _post_military_deploy_bomb ( self , battle_id : int , bomb_id : int ) - > Response :
def _post_military_deploy_bomb ( self , battle_id : int , bomb_id : int ) - > Response :
data = dict ( battleId = battle_id , bombId = bomb_id , _token = self . token )
data = dict ( battleId = battle_id , bombId = bomb_id , _token = self . token )
return self . post ( " {} /military/deploy-bomb " . format ( self . url ) , data = data )
return self . post ( " {} /military/deploy-bomb " . format ( self . url ) , data = data )
def _post_military_fight_air ( self , battle_id : int , side_id : int ) - > Response :
def _post_military_fight_air ( self , battle_id : int , side_id : int , zone_id : int ) - > Response :
data = dict ( sideId = side_id , battleId = battle_id , _token = self . token )
data = dict ( sideId = side_id , battleId = battle_id , _token = self . token , battleZoneId = zone_id )
return self . post ( " {} /military/fight-shoooot/ {} " . format ( self . url , battle_id ) , data = data )
return self . post ( " {} /military/fight-shoooot/ {} " . format ( self . url , battle_id ) , data = data )
def _post_military_fight_ground ( self , battle_id : int , side_id : int ) - > Response :
def _post_military_fight_ground ( self , battle_id : int , side_id : int , zone_id : int ) - > Response :
data = dict ( sideId = side_id , battleId = battle_id , _token = self . token )
data = dict ( sideId = side_id , battleId = battle_id , _token = self . token , battleZoneId = zone_id )
return self . post ( " {} /military/fight-shooot/ {} " . format ( self . url , battle_id ) , data = data )
return self . post ( " {} /military/fight-shooot/ {} " . format ( self . url , battle_id ) , data = data )
def _post_military_group_missions ( self ) - > Response :
def _post_military_group_missions ( self ) - > Response :
@ -897,29 +909,61 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
data = { " _token " : self . token , " post_message " : body }
data = { " _token " : self . token , " post_message " : body }
return self . post ( " {} /main/wall-post/create/json " . format ( self . url ) , data = data )
return self . post ( " {} /main/wall-post/create/json " . format ( self . url ) , data = data )
def _post_main_wall_post_automatic ( self , * * kwargs ) - > Response :
kwargs . update ( _token = self . token )
return self . post ( " {} /main/wall-post/create/json " . format ( self . url ) , data = kwargs )
def _post_main_wall_post_retrieve ( self ) - > Response :
def _post_main_wall_post_retrieve ( self ) - > Response :
data = { " _token " : self . token , " page " : 1 , " switchedFrom " : False }
data = { " _token " : self . token , " page " : 1 , " switchedFrom " : False }
return self . post ( " {} /main/wall-post/retrieve/json " . format ( self . url ) , data = data )
return self . post ( " {} /main/wall-post/retrieve/json " . format ( self . url ) , data = data )
# 12th anniversary endpoints
def _get_anniversary_quest_data ( self ) - > Response :
return self . get ( " {} /main/anniversaryQuestData " . format ( self . url ) )
def _post_map_rewards_unlock ( self , node_id : int ) - > Response :
data = { ' nodeId ' : node_id , ' _token ' : self . token }
return self . post ( " {} /main/map-rewards-unlock " . format ( self . url ) , data = data )
def _post_map_rewards_speedup ( self , node_id : int , currency_amount : int ) - > Response :
data = { ' nodeId ' : node_id , ' _token ' : self . token , " currencyCost " : currency_amount }
return self . post ( " {} /main/map-rewards-speedup " . format ( self . url ) , data = data )
def _post_map_rewards_claim ( self , node_id : int ) - > Response :
data = { ' nodeId ' : node_id , ' _token ' : self . token }
return self . post ( " {} /main/map-rewards-claim " . format ( self . url ) , data = data )
def _post_new_war ( self , self_country_id : int , attack_country_id : int , debate : str = " " ) - > Response :
data = dict ( requirments = 1 , _token = self . token , debate = debate ,
countryNameConfirm = utils . COUNTRY_LINK [ attack_country_id ] )
return self . post ( " {} / {} /new-war " . format ( self . url , utils . COUNTRY_LINK [ self_country_id ] ) , data = data )
def _post_new_donation ( self , country_id : int , amount : int , org_name : str , debate : str = " " ) - > Response :
data = dict ( requirments = 1 , _token = self . token , debate = debate , currency = 1 , value = amount , commit = ' Propose ' ,
type_name = org_name )
return self . post ( " {} / {} /new-donation " . format ( self . url , utils . COUNTRY_LINK [ country_id ] ) , data = data )
class Reporter :
class Reporter :
__to_update : List [ Dict [ Any , Any ] ] = [ ]
__to_update : List [ Dict [ Any , Any ] ] = None
name : str = " "
name : str = " "
email : str = " "
email : str = " "
citizen_id : int = 0
citizen_id : int = 0
key : str = " "
key : str = " "
allowed : bool = False
allowed : bool = False
@property
def __dict__ ( self ) :
return dict ( name = self . name , email = self . email , citizen_id = self . citizen_id , key = self . key , allowed = self . allowed ,
queue = self . __to_update )
def __init__ ( self ) :
def __init__ ( self ) :
self . _req = Session ( )
self . _req = Session ( )
self . url = " https://api.erep.lv "
self . url = " https://api.erep.lv "
self . _req . headers . update ( { " user-agent " : " Bot reporter v2 " } )
self . _req . headers . update ( { " user-agent " : " Bot reporter v2 " } )
self . __to_update = [ ]
self . __registered : bool = False
self . __registered : bool = False
@property
def __dict__ ( self ) :
return dict ( allowed = self . allowed , __to_update = self . __to_update )
def do_init ( self , name : str = " " , email : str = " " , citizen_id : int = 0 ) :
def do_init ( self , name : str = " " , email : str = " " , citizen_id : int = 0 ) :
self . name : str = name
self . name : str = name
self . email : str = email
self . email : str = email
@ -996,7 +1040,7 @@ class MyJSONEncoder(JSONEncoder):
return dict ( 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__ ' ) :
elif hasattr ( o , ' __dict__ ' ) :
return o . __dict__
return o . __dict__
elif isinstance ( o , deque ) :
elif isinstance ( o , ( deque , set ) ):
return list ( o )
return list ( o )
elif isinstance ( o , Citizen ) :
elif isinstance ( o , Citizen ) :
return o . to_json ( )
return o . to_json ( )
@ -1015,71 +1059,84 @@ class BattleSide:
self . allies = [ int ( ally ) for ally in allies ]
self . allies = [ int ( ally ) for ally in allies ]
self . deployed = [ int ( ally ) for ally in deployed ]
self . deployed = [ int ( ally ) for ally in deployed ]
@property
def __dict__ ( self ) :
ret = { }
for key in dir ( self ) :
if not key . startswith ( ' _ ' ) :
ret [ key ] = getattr ( self , key )
return ret
class BattleDivision :
class BattleDivision :
end : datetime . datetime
end : datetime . datetime
epic : bool
epic : bool
dom_pts : Dict [ str , int ] = None
dom_pts : Dict [ str , int ]
wall : Dict [ str , Union [ int , float ] ] = None
wall : Dict [ str , Union [ int , float ] ]
battle_zone_id : int
def_medal : Dict [ str , int ]
inv_medal : Dict [ str , int ]
@property
@property
def div_end ( self ) - > bool :
def div_end ( self ) - > bool :
return utils . now ( ) > = self . end
return utils . now ( ) > = self . end
def __init__ ( self , end : datetime . datetime , epic : bool , inv_pts : int , def_pts : int , wall_for : int , wall_dom : float ) :
def __init__ (
self , div_id : int , end : datetime . datetime , epic : bool , inv_pts : int , def_pts : int ,
wall_for : int , wall_dom : float , def_medal : Tuple [ int , int ] , inv_medal : Tuple [ int , int ]
) :
self . battle_zone_id = div_id
self . end = end
self . end = end
self . epic = epic
self . epic = epic
self . dom_pts = dict ( { " inv " : inv_pts , " def " : def_pts } )
self . dom_pts = dict ( { " inv " : inv_pts , " def " : def_pts } )
self . wall = dict ( { " for " : wall_for , " dom " : wall_dom } )
self . wall = dict ( { " for " : wall_for , " dom " : wall_dom } )
self . def_medal = { " id " : def_medal [ 0 ] , " dmg " : def_medal [ 1 ] }
@property
self . inv_medal = { " id " : inv_medal [ 0 ] , " dmg " : inv_medal [ 1 ] }
def __dict__ ( self ) :
ret = { }
for key in dir ( self ) :
if not key . startswith ( ' _ ' ) :
ret [ key ] = getattr ( self , key )
return ret
class Battle ( object ) :
class Battle :
id : int = 0
id : int
war_id : int = 0
war_id : int
zone_id : int = 0
zone_id : int
is_rw : bool = False
is_rw : bool
is_dict_lib : bool = False
is_dict_lib : bool
start : datetime . datetime = None
start : datetime . datetime
invader : BattleSide = None
invader : BattleSide
defender : BattleSide = None
defender : BattleSide
div : Dict [ int , BattleDivision ] = None
div : Dict [ int , BattleDivision ]
@property
@property
def is_air ( self ) - > bool :
def is_air ( self ) - > bool :
return not bool ( self . zone_id % 4 )
return not bool ( self . zone_id % 4 )
def __init__ ( self , battle : Dict [ str , Any ] ) :
def __init__ ( self , battle : Dict [ str , Any ] = None ) :
self . id = int ( battle . get ( ' id ' , 0 ) )
""" Object representing eRepublik battle.
self . war_id = int ( battle . get ( ' war_id ' , 0 ) )
self . zone_id = int ( battle . get ( ' zone_id ' , 0 ) )
self . is_rw = bool ( battle . get ( ' is_rw ' ) )
self . is_as = bool ( battle . get ( ' is_as ' ) )
self . is_dict_lib = bool ( battle . get ( ' is_dict ' ) ) or bool ( battle . get ( ' is_lib ' ) )
self . start = datetime . datetime . fromtimestamp ( int ( battle . get ( ' start ' , 0 ) ) , tz = utils . erep_tz )
self . invader = BattleSide ( battle . get ( ' inv ' , { } ) . get ( ' id ' ) , battle . get ( ' inv ' , { } ) . get ( ' points ' ) ,
:param battle: Dict object for single battle from ' /military/campaignsJson/list ' response ' s ' battles ' object
[ row . get ( ' id ' ) for row in battle . get ( ' inv ' , { } ) . get ( ' ally_list ' ) ] ,
"""
[ row . get ( ' id ' ) for row in battle . get ( ' inv ' , { } ) . get ( ' ally_list ' ) if row [ ' deployed ' ] ] )
if battle is None :
battle = { }
self . id = 0
self . war_id = 0
self . zone_id = 0
self . is_rw = False
self . is_as = False
self . is_dict_lib = False
self . start = utils . now ( ) . min
self . invader = BattleSide ( 0 , 0 , [ ] , [ ] )
self . defender = BattleSide ( 0 , 0 , [ ] , [ ] )
else :
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 ) )
self . is_rw = bool ( battle . get ( ' is_rw ' ) )
self . is_as = bool ( battle . get ( ' is_as ' ) )
self . is_dict_lib = bool ( battle . get ( ' is_dict ' ) ) or bool ( battle . get ( ' is_lib ' ) )
self . start = datetime . datetime . fromtimestamp ( int ( battle . get ( ' start ' , 0 ) ) , tz = utils . erep_tz )
self . defen der = BattleSide ( battle . get ( ' def ' , { } ) . get ( ' id ' ) , battle . get ( ' def ' , { } ) . get ( ' points ' ) ,
self . inva der = BattleSide (
[ row . get ( ' id ' ) for row in battle . get ( ' def ' , { } ) . get ( ' ally_list ' ) ] ,
battle . get ( ' inv ' , { } ) . get ( ' id ' ) , battle . get ( ' inv ' , { } ) . get ( ' points ' ) ,
[ row . get ( ' id ' ) for row in battle . get ( ' def ' , { } ) . get ( ' ally_list ' ) if row [ ' deployed ' ] ] )
[ row . get ( ' id ' ) for row in battle . get ( ' inv ' , { } ) . get ( ' ally_list ' ) ] ,
[ row . get ( ' id ' ) for row in battle . get ( ' inv ' , { } ) . get ( ' ally_list ' ) if row [ ' deployed ' ] ]
)
self . defender = BattleSide (
battle . get ( ' def ' , { } ) . get ( ' id ' ) , battle . get ( ' def ' , { } ) . get ( ' points ' ) ,
[ 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 = { }
self . div = { }
for div , data in battle . get ( ' div ' , { } ) . items ( ) :
for div , data in battle . get ( ' div ' , { } ) . items ( ) :
@ -1089,11 +1146,18 @@ class Battle(object):
else :
else :
end = utils . localize_dt ( datetime . datetime . max - datetime . timedelta ( days = 1 ) )
end = utils . localize_dt ( datetime . datetime . max - datetime . timedelta ( days = 1 ) )
battle_div = B attleDivision (
if not d ata [ ' stats ' ] [ ' def ' ] :
end = end , epic = data . get ( ' epic_type ' ) in [ 1 , 5 ] ,
def_medal = ( 0 , 0 )
inv_pts = data . get ( ' dom_pts ' ) . get ( " inv " ) , def_pts = data . get ( ' dom_pts ' ) . get ( " def " ) ,
else :
wall_for = data . get ( ' wall ' ) . get ( " for " ) , wall_dom = data . get ( ' wall ' ) . get ( " dom " )
def_medal = ( data [ ' stats ' ] [ ' def ' ] [ ' citizenId ' ] , data [ ' stats ' ] [ ' def ' ] [ ' damage ' ] )
)
if not data [ ' stats ' ] [ ' inv ' ] :
inv_medal = ( 0 , 0 )
else :
inv_medal = ( data [ ' stats ' ] [ ' inv ' ] [ ' citizenId ' ] , data [ ' stats ' ] [ ' inv ' ] [ ' damage ' ] )
battle_div = BattleDivision ( end = end , epic = data . get ( ' epic_type ' ) in [ 1 , 5 ] , div_id = data . get ( ' id ' ) ,
inv_pts = data . get ( ' dom_pts ' ) . get ( " inv " ) , def_pts = data . get ( ' dom_pts ' ) . get ( " def " ) ,
wall_for = data . get ( ' wall ' ) . get ( " for " ) , wall_dom = data . get ( ' wall ' ) . get ( " dom " ) ,
def_medal = def_medal , inv_medal = inv_medal )
self . div . update ( { div : battle_div } )
self . div . update ( { div : battle_div } )
@ -1104,17 +1168,10 @@ class Battle(object):
time_part = " {} " . format ( now - self . start )
time_part = " {} " . format ( now - self . start )
else :
else :
time_part = " - {} " . format ( self . start - now )
time_part = " - {} " . format ( self . start - now )
return " Battle {} | {:>21.21} : {:<21.21} | Round {:2} | Start {} " . format (
return f " Battle {self . id } | " \
self . id , utils . COUNTRIES [ self . invader . id ] , utils . COUNTRIES [ self . defender . id ] , self . zone_id , time_part
f " { utils . COUNTRIES [ self . invader . id ] : >21.21 } : { utils . COUNTRIES [ self . defender . id ] : <21.21 } | " \
)
f " Round { self . zone_id : 2 } | " \
f " Time since start { time_part } "
@property
def __dict__ ( self ) :
ret = { }
for key in dir ( self ) :
if not key . startswith ( ' _ ' ) :
ret [ key ] = getattr ( self , key )
return ret
class EnergyToFight :
class EnergyToFight :
@ -1150,33 +1207,49 @@ class EnergyToFight:
class TelegramBot :
class TelegramBot :
__initialized = False
__initialized = False
__queue : List [ str ] = [ ]
__queue : List [ str ]
chat_id = 0
chat_id = 0
api_url = " "
api_url = " "
player_name = " "
player_name = " "
__last_time : datetime . datetime = None
__thread_stopper : threading . Event
_last_time : datetime . datetime
_last_full_energy_report : datetime . datetime
_next_time : datetime . datetime
_threads : List [ threading . Thread ]
def __init__ ( self , stop_event : threading . Event = None ) :
self . _threads = [ ]
self . __queue = [ ]
self . __thread_stopper = threading . Event ( ) if stop_event is None else stop_event
def __dict__ ( self ) :
return dict ( chat_id = self . chat_id , api_url = self . api_url , player = self . player_name , last_time = self . _last_time ,
next_time = self . _next_time , queue = self . __queue , initialized = self . __initialized ,
has_threads = bool ( len ( self . _threads ) ) )
def do_init ( self , chat_id : int , token : str , player_name : str = " " ) :
def do_init ( self , chat_id : int , token : str , player_name : str = " " ) :
self . chat_id = chat_id
self . chat_id = chat_id
self . api_url = " https://api.telegram.org/bot {} /sendMessage " . format ( token )
self . api_url = " https://api.telegram.org/bot {} /sendMessage " . format ( token )
self . player_name = player_name
self . player_name = player_name
self . __initialized = True
self . __initialized = True
self . __ last_time = utils . good_timedelta ( utils . now ( ) , datetime . timedelta ( minutes = - 5 ) )
self . _last_time = utils . good_timedelta ( utils . now ( ) , datetime . timedelta ( minutes = - 5 ) )
self . _last_full_energy_report = utils . good_timedelta ( utils . now ( ) , datetime . timedelta ( minutes = - 30 ) )
if self . __queue :
if self . __queue :
self . send_message ( " \n \n – – – – – – – – – – – – – – – – – – – – – – \n \n " . join ( self . __queue ) )
self . send_message ( " \n \n – – – – – – – – – – – – – – – – – – – – – – \n \n " . join ( self . __queue ) )
def send_message ( self , message : str ) - > bool :
def send_message ( self , message : str ) - > bool :
self . __queue . append ( message )
if not self . __initialized :
if not self . __initialized :
self . __queue . append ( message )
return True
return True
if self . player_name :
self . _threads = [ t for t in self . _threads if t . is_alive ( ) ]
message = f " Player * { self . player_name } * \n " + message
self . _next_time = utils . good_timedelta ( utils . now ( ) , datetime . timedelta ( minutes = 1 ) )
if utils . good_timedelta ( utils . now ( ) , datetime . timedelta ( seconds = - 1 ) ) < = self . __last_time :
if not self . _threads :
tb = traceback . extract_stack ( )
name = " telegram_ {} send " . format ( f " { self . player_name } _ " if self . player_name else " " )
message + = " \n \n ``` \n {} \n ``` " . format ( " \n " . join ( [ ' File " {} " , line {} , in {} \n ' . format ( l . filename , l . lineno , l . name ) for l in tb ] ) )
send_thread = threading . Thread ( target = self . __send_messages , name = name )
response = post ( self . api_url , json = dict ( chat_id = self . chat_id , text = message , parse_mode = " Markdown " ) )
send_thread . start ( )
self . __last_time = utils . now ( )
self . _threads . append ( send_thread )
return response . json ( ) . get ( ' ok ' )
return True
def report_free_bhs ( self , battles : List [ Tuple [ int , int , int , int , datetime . timedelta ] ] ) :
def report_free_bhs ( self , battles : List [ Tuple [ int , int , int , int , datetime . timedelta ] ] ) :
battle_links = [ ]
battle_links = [ ]
@ -1195,8 +1268,26 @@ class TelegramBot:
self . send_message ( " Free BHs: \n " + " \n " . join ( battle_links ) )
self . send_message ( " Free BHs: \n " + " \n " . join ( battle_links ) )
def report_full_energy ( self , available : int , limit : int , interval : int ) :
def report_full_energy ( self , available : int , limit : int , interval : int ) :
message = f " F ull energy ( { available } hp/ { limit } hp + { interval } hp/6min) "
if ( utils . now ( ) - self . _last_f ull_ energy_report ) . total_seconds ( ) > = 30 * 60 :
self . send_message ( message )
self . _last_full_energy_report = utils . now ( )
message = f " Full energy ( { available } hp/ { limit } hp + { interval } hp/6min) "
self . send_message ( message )
def report_medal ( self , msg ) :
def report_medal ( self , msg ) :
self . send_message ( f " New award: * { msg } * " )
self . send_message ( f " New award: * { msg } * " )
def __send_messages ( self ) :
while self . _next_time > utils . now ( ) :
if self . __thread_stopper . is_set ( ) :
break
self . __thread_stopper . wait ( utils . get_sleep_seconds ( self . _next_time ) )
message = " \n \n – – – – – – – – – – – – – – – – – – – – – – \n \n " . join ( self . __queue )
if self . player_name :
message = f " Player * { self . player_name } * \n " + message
response = post ( self . api_url , json = dict ( chat_id = self . chat_id , text = message , parse_mode = " Markdown " ) )
self . _last_time = utils . now ( )
if response . json ( ) . get ( ' ok ' ) :
self . __queue = [ ]
return True
return False