This repository has been archived by the owner on Jul 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmarketbot.py
132 lines (109 loc) · 4.77 KB
/
marketbot.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
from enum import Enum
from random import random
from time import sleep
from timeit import default_timer
import mss
import pyautogui
from PyQt5.QtCore import *
from buyer import evaluate_listing
from screenshotter import ScreenShotter
from screenwatcher import ScreenWatcher
from windowtitle import get_foreground_window_title
pyautogui.PAUSE = 0.1
pyautogui.FAILSAFE = False
PURCHASE_OFFSET = 1730, 185
TRADING_BUTTON = 1268, 1065
class State(Enum):
WAIT_FOR_REFRESH = 0
WAIT_FOR_LISTINGS = 1
WAIT_FOR_BUY_BUTTON = 2
WAIT_FOR_BUY_RESULT = 3
# noinspection PyArgumentList
class MarketBot(QThread):
listings_signal = pyqtSignal(object)
successful_buy_signal = pyqtSignal(object)
# fault_signal = pyqtSignal(object) # TODO (eg. Item move error)
def __init__(self, parentQWidget=None):
super(MarketBot, self).__init__(parentQWidget)
self.screenwatcher = None
self.buying = False
self.price = None
self.state = State.WAIT_FOR_LISTINGS
self.next_refresh = 0
self.listings = None
self.last_buy_number = None
self.unavailable_listings = None
@pyqtSlot(bool)
def buying_changed(self, buying):
self.buying = buying
@pyqtSlot(int)
def price_changed(self, price):
self.price = price
def run(self):
with ScreenShotter() as sct:
self.screenwatcher = ScreenWatcher(sct)
while True:
if not self.buying or not get_foreground_window_title() == "EscapeFromTarkov":
self.state = State.WAIT_FOR_REFRESH
sleep(0.5)
continue
if self.state is State.WAIT_FOR_REFRESH:
if self.next_refresh < default_timer():
self.refresh()
sleep(0.08)
self.next_refresh = default_timer() + self.refresh_interval()
self.unavailable_listings = set()
self.state = State.WAIT_FOR_LISTINGS
elif self.next_refresh + 10 < default_timer():
print("Stuck failsafe triggered")
error = self.screenwatcher.find_error_ok_button()
if error:
pyautogui.click(error)
pyautogui.click(TRADING_BUTTON)
sleep(1)
self.state = State.WAIT_FOR_REFRESH
elif self.state is State.WAIT_FOR_LISTINGS:
self.listings = self.screenwatcher.find_listings()
if self.listings:
print(self.listings)
self.listings_signal.emit(self.listings)
self.state = State.WAIT_FOR_BUY_BUTTON
elif self.state is State.WAIT_FOR_BUY_BUTTON:
wait_more = False
buyable_items = self.screenwatcher.find_purchase_buttons() - self.unavailable_listings
for i in range(0, len(self.listings)):
if i not in self.unavailable_listings and evaluate_listing(self.listings[i], self.price):
wait_more = True
if i in buyable_items:
self.buy(i)
self.state = State.WAIT_FOR_BUY_RESULT
break
if not wait_more:
self.state = State.WAIT_FOR_REFRESH
elif self.state is State.WAIT_FOR_BUY_RESULT:
if self.last_buy_number in self.screenwatcher.find_purchase_or_outofstock():
sleep(0.1)
error = self.screenwatcher.find_error_ok_button()
if error:
print("\tFAIL")
self.unavailable_listings.add(self.last_buy_number)
pyautogui.click(error)
self.state = State.WAIT_FOR_BUY_BUTTON
else:
print("\tSUCCESS")
self.successful_buy_signal.emit(self.listings[self.last_buy_number])
self.state = State.WAIT_FOR_LISTINGS
def refresh(self):
# Todo: right click filter by item
self.listings = None
pyautogui.press('f5')
def refresh_interval(self):
# Todo intelligent backoff based on price
return 3.1 + random()
def buy(self, listing_no):
self.last_buy_number = listing_no
listing = self.listings[listing_no]
print("Buying {}".format(listing))
pyautogui.click(x=PURCHASE_OFFSET[0], y=PURCHASE_OFFSET[1] + listing.coord)
pyautogui.press('y')
pyautogui.moveTo(x=PURCHASE_OFFSET[0], y=120)