-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsend_troops.py
195 lines (155 loc) · 7.39 KB
/
send_troops.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import os
from asyncio import sleep
from datetime import datetime
from time import time
from ast import literal_eval
from copy import copy
from credentials import SERVER_URL
from random import randint
from bs4 import BeautifulSoup
from authorization import logged_in_session
from logger import info_logger_for_future_events, get_logger
logger = get_logger(__name__)
ATTACK_TYPE = {'c': 4}
TROOPS = {'t' + str(i): 0 for i in range(1, 12)}
class TroopsOrder:
"""Creates an order for troops and send them to concrete point with timing."""
def __init__(self, barrack_url, village_number):
self.barrack_url = barrack_url
self.session = None
self.troops = copy(TROOPS)
self.troops_to_send = copy(TROOPS)
self.type = dict(ATTACK_TYPE)
self.file_name = f'/tmp/RAIDS_{village_number}'
self.attacks = []
self.sent_troops = False
async def __call__(self, *args, **kwargs):
self.sent_troops = False
if not self.attacks:
with open(self.file_name) as f:
self.attacks += [line.rstrip('\n') for line in f]
self.attacks = list(dict.fromkeys(self.attacks))
if self.attacks:
self.session = logged_in_session()
else:
await sleep(60)
return
self.parse_troops_amount()
for attack in self.attacks:
self.troops_to_send = copy(TROOPS)
await sleep(randint(6, 14))
coords, troops = attack.split(';')
try:
x, y = coords.split('|')
x = int(x[1:])
y = int(y[:-1])
self.coords = {'x': x, 'y': y}
troops = literal_eval(troops)
except Exception as e:
msg = str(e).lower()
logger.error('Removing raid, wrong input\n' + msg)
self.attacks.remove(attack)
self.troops_to_send.update(troops)
diffkeys = [k for k in self.troops_to_send.keys() if self.troops_to_send[k] != TROOPS[k]]
if not diffkeys:
continue
if not self.troops_available():
success = self.use_available_troops()
if not success:
continue
# self.send_troops()
self.sent_troops = True
self.attacks.remove(attack)
if self.sent_troops is False:
time_to_return = self.time_for_troops_to_return()
if time_to_return:
random = randint(30, 300)
info_logger_for_future_events('Didnt send any attack, waiting for return until ', time_to_return + random)
await sleep(time_to_return + random)
else:
random = randint(3600, 4100)
info_logger_for_future_events('Didnt send any attack and no one returning, waiting until ', random)
await sleep(random)
def send_troops(self):
"""The main function"""
barrack_page = self.session.get(self.barrack_url).text
barrack_parser = BeautifulSoup(barrack_page, 'html.parser')
hidden_inputs_tags = barrack_parser.find_all('input', {'type': 'hidden'})
post_data = {tag['name']: tag['value'] for tag in hidden_inputs_tags}
post_data.update(self.troops_to_send)
post_data.update(self.coords)
post_data.update(self.type)
post_data['dname'] = ''
post_data['s1'] = 'ok'
confirmation = self.session.post(SERVER_URL + 'build.php?gid=16&tt=2', data=post_data).text
confirmation_parser = BeautifulSoup(confirmation, 'html.parser')
# self.parse_time_of_next_raid(confirmation_parser)
hidden_inputs_tags = confirmation_parser.find_all('input', {'type': 'hidden'})
post_data = {tag['name']: tag['value'] for tag in hidden_inputs_tags}
self.session.post(self.barrack_url, data=post_data)
logger.info('Sending troops to: ({}|{})'.format(self.coords['x'], self.coords['y']))
self.sent_troops = True
def parse_troops_amount(self):
"""Parse amount of troops and save of to property"""
overview_page_link = self.barrack_url.replace('tt=2', 'tt=1')
overview_page = self.session.get(overview_page_link).text
overview_page_parser = BeautifulSoup(overview_page, 'html.parser')
# Get tags with amount of units.
# unit_name_tags = overview_page_parser.find_all('img', class_='unit')
overview_page_parser = overview_page_parser.find_all(class_="troop_details")
for page in overview_page_parser:
if 'Vlastní jednotky' in page.text:
overview_page_parser = page
break
unit_amount_tags = overview_page_parser.find_all('td', class_='unit')
# Create dictionary with troops information
# troops_amount = {name['alt']: amount.text for name, amount in zip(unit_name_tags, unit_amount_tags)}
troops_amount = {'t{}'.format(i+1): int(unit_amount_tags[i].text) for i in range(len(unit_amount_tags))}
self.troops = troops_amount
def parse_time_of_next_raid(self, confirmation_parser):
"""Compute time to next raid. Takes parser of confirmation page"""
timer_element = confirmation_parser.find('div', class_='at').contents[1]
arrival_time_in_seconds = int(timer_element['value'])
arrival_time = datetime.fromtimestamp(arrival_time_in_seconds) - datetime.now()
seconds_to_come_back = arrival_time.total_seconds() * 2
come_back_time = time() + seconds_to_come_back
self.time_of_next_raid = come_back_time
def save_next_raid_time(self):
"""Save coords and time for next raid in file."""
with open("raids.txt", "rt") as file_input:
with open("new_raids.txt", "wt") as file_output:
for line in file_input:
if str(self.coords) in line:
file_output.write(str(self.coords) + ';' + str(self.time_of_next_raid) + '\n')
else:
file_output.write(line)
os.rename('new_raids.txt', "raids.txt")
def troops_available(self):
"""Determine what type of troops will be sent based on their availability. Return type and amount"""
for key, value in self.troops.items():
if value < self.troops_to_send[key]:
return False
return True
def use_available_troops(self):
self.troops_to_send = copy(TROOPS)
if self.troops['t5'] >= 6:
self.troops_to_send.update({'t5': 6})
logger.info("Don't have enough troops, sending 6 EIs")
return True
if self.troops['t3'] >= 6:
self.troops_to_send.update({'t3': 6})
logger.info("Don't have enough troops, sending 6 Imperians")
return True
if self.troops['t1'] >= 6:
self.troops_to_send.update({'t1': 6})
logger.info("Don't have enough troops, sending 6 Leggos")
return True
def time_for_troops_to_return(self):
overview_page_link = self.barrack_url.replace('tt=2', 'tt=1')
overview_page = self.session.get(overview_page_link).text
overview_page_parser = BeautifulSoup(overview_page, 'html.parser')
try:
back_time = int(overview_page_parser.find(class_="troop_details outRaid").find(class_="timer").get('value'))
except:
back_time = 0
return back_time