-
Notifications
You must be signed in to change notification settings - Fork 0
/
bmw.py
113 lines (96 loc) · 3.94 KB
/
bmw.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
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager
import os
import telegram_send
# supress web driver manager logs
os.environ['WDM_LOG'] = '0'
CHROME_BINARY_PATH = 'C:\\Program Files\\Google\Chrome\\Application\\chrome.exe'
USERNAME = "[email protected]"
PASSWORD = "your_my_garage_password"
MY_GARAGE_URL = "https://mygarage.bmwusa.com/"
NUM_INPUT_TAGS = 2
CREDENTIALS_TAG = "input"
LOGIN_BUTTON_CLASS_NAME = ".custom-button.__b.primary"
VEHICLE_VIN_CLASS_NAME = "mbg__vehicle-vinprod"
VEHICLE_PRODUCTION_STATUS_TAG = "div"
VEHICLE_PRODUCTION_STATUS_CLASS_NAME = "mbg__vehicle-status"
TIMEOUT = 10 # in seconds
def main():
global driver
options = Options()
options.add_argument('--no-sandbox')
options.add_argument('--ignore-certificate-errors')
options.add_argument('--incognito')
options.add_argument('--disable-extensions')
options.add_argument('--headless')
options.add_experimental_option("excludeSwitches", ["enable-logging"])
options.binary_location = CHROME_BINARY_PATH
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
try:
driver.get(MY_GARAGE_URL)
except Exception as ex:
cleanUpAndExit(ex)
# wait for the login screen to fully load
implicitWaitForPageLoad(By.CSS_SELECTOR, LOGIN_BUTTON_CLASS_NAME)
# log in
performLogin(USERNAME, PASSWORD)
# wait for my garage to fully load
implicitWaitForPageLoad(By.CLASS_NAME, VEHICLE_VIN_CLASS_NAME)
# save the previous status
prevStatus = getPreviousStatus()
# fetch the production status
productionStatus = getProductionStatus(BeautifulSoup(driver.page_source, 'html.parser'))
# write production status to file
writeProductionStatusToFile(productionStatus)
# send updates via telegram
sendStatusViaTelegram(prevStatus, productionStatus)
print(productionStatus)
cleanUpAndExit()
def getStatusFileName():
return os.path.dirname(os.path.realpath(__file__)) + "\status.txt"
def getPreviousStatus():
fileName = getStatusFileName()
if not os.path.exists(fileName):
return ""
with open(fileName, "r") as file:
return file.read()
def writeProductionStatusToFile(status):
with open(getStatusFileName(), "w") as file:
file.write(status)
def sendStatusViaTelegram(prevStatus, newStatus):
# only send updates if the new status is different
if prevStatus != newStatus:
message = prevStatus + "->" + newStatus
telegram_send.send(messages=["`" + message + "`"], parse_mode="markdown")
def getProductionStatus(html):
statusWithExtras = html.find_all(VEHICLE_PRODUCTION_STATUS_TAG,
{"class": VEHICLE_PRODUCTION_STATUS_CLASS_NAME})[0]
return statusWithExtras.text.split(": ", 1)[1]
def performLogin(username, password):
# find the username and password fields
inputTags = driver.find_elements(By.TAG_NAME, CREDENTIALS_TAG)
if len(inputTags) < NUM_INPUT_TAGS:
cleanUpAndExit("Not all input tags were found. Quitting...")
usernameField = inputTags[0]
passwordField = inputTags[1]
loginButton = driver.find_elements(By.CSS_SELECTOR, LOGIN_BUTTON_CLASS_NAME)[0]
usernameField.send_keys(username)
passwordField.send_keys(password)
loginButton.click()
def implicitWaitForPageLoad(locator, locatorValue):
try:
WebDriverWait(driver, TIMEOUT).until(EC.visibility_of_any_elements_located((locator,
locatorValue)))
except:
cleanUpAndExit("implicitWaitForPageLoad timed out - locatorValue: " + locatorValue)
def cleanUpAndExit(message = ""):
driver.quit()
exit(message)
if __name__ == "__main__":
main()