-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoda.py
More file actions
117 lines (103 loc) · 3.22 KB
/
oda.py
File metadata and controls
117 lines (103 loc) · 3.22 KB
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
import requests
from dotenv import load_dotenv
import os
from bs4 import BeautifulSoup
load_dotenv()
class Oda:
def __init__(self):
self.csrftoken = None
self.requests = requests.session()
def login(self, username, password):
response = self.requests.get('https://oda.com/no/user/login/')
csrf_middleware_token = self._get_csrf_middleware_token(response.text)
body = {
"csrfmiddlewaretoken": csrf_middleware_token,
"username": username,
"password": password,
}
response = self.requests.post('https://oda.com/no/user/login/',
headers={
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Referer": "https://oda.com/no/user/login/",
"Content-Type": "application/x-www-form-urlencoded",
},
data=body
)
self.csrftoken = response.cookies.get_dict()["csrftoken"]
return self
def prepare_checkout(self, delivery_slot_id):
payload = {
"delivery_slot_id":delivery_slot_id,
"is_unattended_delivery":True,
"in_modal":False,
"delivery_address_id":os.getenv("DELIVERY__ID")
}
self.requests.post("https://oda.com/api/v1/slot-picker/info/",
headers={
"Accept": "application/json",
"Cookie": self.cookie,
"X-CSRFToken": self.csrftoken,
"Referer": "https://oda.com/no/checkout/delivery/time/",
},
json=payload)
return self
def add_gifflar_to_cart(self):
self.requests.post("https://oda.com/no/cart/products/",
headers={
"Accept": "*/*",
"Content-Type": "application/json; charset=UTF-8",
"X-CSRFToken": self.csrftoken,
"Referer": "https://oda.com/no/search/?q=gifflar",
},
json=[{"product_id":"11470","quantity":1,"delete":False,"tracking_location":"Cart"}],
)
return self
def get_next_delivery_slot(self):
response = self.requests.get("https://oda.com/api/v1/slot-picker/slots/?from-index=3&num-days=3",
headers={
"Accept": "*/*",
},
)
results = response.json()
for i in results['delivery_slots']:
if not i['is_unavailable']:
return i
return None
def submit(self):
html = self.requests.get("https://oda.com/no/checkout/confirm/").text
csrf_middleware_token = self._get_csrf_middleware_token(html)
body = {
"csrfmiddlewaretoken": csrf_middleware_token,
"22-storedPaymentMethodId": os.getenv("PAYMENT_METHOD"),
"22-colorDepth": "24",
"22-javaEnabled": "false",
"22-language": "en-US",
"22-screenHeight": "1080",
"22-screenWidth": "1920",
"22-timeZoneOffset": "-60",
}
response = self.requests.post("https://oda.com/no/checkout/confirm/22/",
headers={
"Accept": "application/json",
"X-CSRFToken": self.csrftoken,
"Referer": "https://oda.com/no/checkout/confirm/",
"Content-Type": "application/x-www-form-urlencoded",
},
data=body
)
def _get_csrf_middleware_token(self, html):
soup = BeautifulSoup(html, 'html.parser')
csrf_middleware_token = soup.find("input", {
"name":"csrfmiddlewaretoken"
}).attrs["value"]
return csrf_middleware_token
if __name__ == "__main__":
oda = Oda().login(
os.getenv("EMAIL"),
os.getenv("PASSWORD")
)
delivery_slot = oda.get_next_delivery_slot()
if delivery_slot is None:
raise Exception("Did not find a delivery slot")
oda.prepare_checkout(delivery_slot['id'])
oda.submit()