-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsbf.py
152 lines (111 loc) · 5.31 KB
/
sbf.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
import globals as g, web_modules as wm, alert_modules as am, web_utilities.browser as browser, ascii
import time, importlib
# Represents the products which have already been purchased. This is used to ensure only one specific product will be bought.
purchased = {}
# Represents the state of the product. This is used to 'check' when the product has stock and when it is out of stock. It will be initially set to False.
has_stock = {}
def process_url(driver, url, action):
'''Notify about stock change by calling the specific alert module.
Arguments:
- driver: web_utilities.Browser
Instance of the Browser class that will open the URL and retrieve its HTML.
- url: str
Website link where the specific product is being sold.
- action: str
Variable used to know what action to take: check stock, buy the product, etc...
Return:
- bool
True if action performed successfully, False otherwise.'''
specific_module = None
for module in g.webmodules:
if url.startswith(module):
try:
# Get a specific web_module based on the relationship established in g.webmodules
specific_module = importlib.import_module('.' + g.webmodules[module], package=wm.__name__)
# Call the action related method of the specific web_module
return getattr(specific_module, action)(driver, url)
except ModuleNotFoundError:
print('[!!] Error: web_module "' + g.webmodules[module] + '" could not be found\n')
return False
except AttributeError:
print('[!!] Error: web_module "' + g.webmodules[module] + '" has no method for the "' + action + '" action\n')
return False
if specific_module is None:
print('[!!] Error: no web_module exists for "' + url + '"\n')
return False
def alert(url, action, state):
'''Notify about stock change by calling the specific alert module.
Arguments:
- url: str
Website link where the specific product is being sold.
- action: str
Variable used to alert if the product stock has been checked or purchased.
- state: bool
Variable used to keep track of changes in product stock.
Return: None'''
specific_module = None
for module in g.alertmodules:
if module == action:
try:
# Get a specific alert_module based on the relationship established in g.alertmodules
specific_module = importlib.import_module('.' + g.alertmodules[module], package=am.__name__)
# Call the action related method of the specific alert_module
getattr(specific_module, action)(url, state)
except ModuleNotFoundError:
print('[!!] Error: alert_module "' + g.alertmodules[module] + '" could not be found\n')
except AttributeError:
print('[!!] Error: alert_module "' + g.alertmodules[module] + '" has no "' + action + '" method\n')
if specific_module is None:
print('[!!] Error: no alert_module exists for "' + action + '"\n')
def execute():
'''Main loop of the bot, it processes all URLs based on the action specified and alerts the user of any changes.
It finishes when all the products with distinct ID have been purchased.
Arguments: None
Return: None'''
all_purchased = False
driver = browser.Browser()
try:
while not all_purchased:
all_purchased = False
time.sleep(g.time_interval)
for product in g.product_list:
product_id = product[0]
url = product[1]
action = product[2]
if not purchased[product_id]:
driver.start_driver()
result = process_url(driver, url, action)
if has_stock[url] is not result:
purchased[product_id] = action == 'buy'
has_stock[url] = result
alert(url, action, result)
driver.stop_driver()
for purchased_product in purchased:
all_purchased = all_purchased and purchased_product
except KeyboardInterrupt:
print('\n[!!] Stopping execution...\n')
del driver
def init():
'''Initialize variables before the main execution of the bot.
Arguments: None
Return: None'''
g.init_globals()
ascii.print_ascii_title()
if not hasattr(g, 'product_list') or g.product_list is None or len(g.product_list) <= 0:
print('[!!] Error: product_list must be initialized with some product URLs\n')
return False
if not hasattr(g, 'time_interval') or g.time_interval is None or g.time_interval < 0:
print('[!!] Error: time_interval must be set to a number larger than or equal to 0\n')
return False
for product in g.product_list:
# Initially set all the products as not purchased and set the stock state of all urls as False
product_id = product[0]
url = product[1]
purchased[product_id] = False
has_stock[url] = False
return True
def main():
if init():
execute()
if __name__ == '__main__':
main()