├── .gitignore
├── README.md
├── catalog.py
├── config.example.json
├── consumerKey.py
└── nugget.py
/.gitignore:
--------------------------------------------------------------------------------
1 | config.json
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Operation-Chicken-Nugget
2 |
3 | Goal of this Operation is, grabbing a KS1 in Roubaix.
4 | **Don't run this on a VPS, you will get flagged for Fraud**
5 |
6 | **Dependencies**
7 |
8 | ```
9 | pip3 install requests ovh
10 | ```
11 |
12 | 1. Create an Application
13 | https://ca.api.ovh.com/createApp/
14 | https://eu.api.ovh.com/createApp/
15 |
16 | 2. Put the keys into config.json
17 | Example how config.json should look like by now
18 |
19 | ```
20 | {
21 | "endpoint":"ovh-ca",
22 | "endpointAPI":"ca.api.ovh.com",
23 | "ovhSubsidiary":"CA",
24 | "application_key":"xxxxxxxxxx",
25 | "application_secret":"xxxxxxxxxxxxxxxxxx",
26 | "dedicated_datacenter":"fr",
27 | "region":"europe",
28 | "consumer_key":""
29 | }
30 | ```
31 |
32 | 2. Request the consumerKey with running consumerKey.py and put it into config.json
33 |
34 | 3. Edit nugget.py if you want to, by default it does no autopay and only in RBX
35 | If you want GRA, uncomment a few lines.
36 |
37 | 4. Profit!
38 |
--------------------------------------------------------------------------------
/catalog.py:
--------------------------------------------------------------------------------
1 | import requests
2 |
3 | endpoint = "ca.api.ovh.com"
4 | response = requests.get(f'https://{endpoint}/1.0/order/catalog/public/eco?ovhSubsidiary=WE')
5 | catalog = response.json()
6 | catalogSorted = {}
7 | for plan in catalog['plans']:
8 | for price in plan['pricings']:
9 | if "installation" in price['capacities']: continue
10 | if price['interval'] != 1: continue
11 | catalogSorted[price['price']] = plan
12 |
13 | newlist = dict(sorted(catalogSorted.items(), key=lambda item: item[0]))
14 |
15 | for price,offer in newlist.items():
16 | if "product" in offer:
17 | print(price,offer["invoiceName"])
18 | for addon in offer['addonFamilies']:
19 | if addon['mandatory'] != True: continue
20 | print(addon)
21 |
--------------------------------------------------------------------------------
/config.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "endpoint":"",
3 | "ovhSubsidiary":"",
4 | "application_key":"",
5 | "application_secret":"",
6 | "dedicated_datacenter":"",
7 | "region":"",
8 | "consumer_key":""
9 | }
--------------------------------------------------------------------------------
/consumerKey.py:
--------------------------------------------------------------------------------
1 | import json, ovh
2 |
3 | with open('config.json') as f:
4 | config = json.load(f)
5 |
6 | # create a client using configuration
7 | client = ovh.Client(
8 | endpoint=config['endpoint'],
9 | application_key=config['application_key'],
10 | application_secret=config['application_secret']
11 | )
12 |
13 | # Request RO, /me API access
14 | ck = client.new_consumer_key_request()
15 | ck.add_recursive_rules(ovh.API_READ_WRITE, "/")
16 |
17 | # Request token
18 | validation = ck.request()
19 |
20 | print("Please visit %s to authenticate" % validation['validationUrl'])
21 | input("and press Enter to continue...")
22 |
23 | # Print nice welcome message
24 | print("Welcome", client.get('/me')['firstname'])
25 | print("Btw, your 'consumerKey' is '%s'" % validation['consumerKey'])
--------------------------------------------------------------------------------
/nugget.py:
--------------------------------------------------------------------------------
1 | import requests, hashlib, json, time, ovh
2 | from datetime import datetime
3 | from random import randint
4 |
5 | with open('config.json') as f:
6 | config = json.load(f)
7 |
8 | # Instantiate. Visit https://api.ovh.com/createToken/?GET=/me
9 | # to get your credentials
10 | client = ovh.Client(
11 | endpoint=config['endpoint'],
12 | application_key=config['application_key'],
13 | application_secret=config['application_secret'],
14 | consumer_key=config['consumer_key'],
15 | )
16 |
17 | # Print nice welcome message
18 | print("Welcome", client.get('/me')['firstname'])
19 |
20 | headers = {'Accept': 'application/json','X-Ovh-Application':config['application_key'],'X-Ovh-Consumer':config['consumer_key'],
21 | 'Content-Type':'application/json;charset=utf-8','Host':config['endpointAPI']}
22 | print("Preparing Package")
23 | #getting current time
24 | response = requests.get(f"https://{config['endpointAPI']}/1.0/auth/time", headers=headers)
25 | if response.status_code == 200:
26 | print("Getting Time")
27 | else:
28 | print(response.status_code)
29 | print(json.dumps(response.json(), indent=4))
30 | exit()
31 | timeDelta = int(response.text) - int(time.time())
32 | #run for 8 days
33 | for day in range(4):
34 | print(f'Day {day}')
35 | # creating a new cart
36 | cart = client.post("/order/cart", ovhSubsidiary=config['ovhSubsidiary'], _need_auth=False)
37 | #assign new cart to current user
38 | client.post("/order/cart/{0}/assign".format(cart.get("cartId")))
39 | #put ks1 into cart
40 | #result = client.post(f'/order/cart/{cart.get("cartId")}/eco',{"duration":"P1M","planCode":"22sk010","pricingMode":"default","quantity":1})
41 | #apparently this shit sends malformed json whatever baguette
42 | payload={'duration':'P1M','planCode':'22sk010','pricingMode':'default','quantity':1}
43 | response = requests.post(f"https://{config['endpointAPI']}/1.0/order/cart/{cart.get('cartId')}/eco", headers=headers, data=json.dumps(payload))
44 | if response.status_code != 200:
45 | print(response.status_code)
46 | print(json.dumps(response.json(), indent=4))
47 | exit()
48 | #getting current cart
49 | response = requests.get(f"https://{config['endpointAPI']}/1.0/order/cart/{cart.get('cartId')}")
50 | if response.status_code != 200:
51 | print(response.status_code)
52 | print(json.dumps(response.json(), indent=4))
53 | exit()
54 | #modify item for checkout
55 | itemID = response.json()['items'][0]
56 | print(f'Getting current cart {cart.get("cartId")}')
57 | #set configurations
58 | configurations = [{'label':'region','value':config['region']},{'label':'dedicated_datacenter','value':config['dedicated_datacenter']},{'label':'dedicated_os','value':'none_64.en'}]
59 | for entry in configurations:
60 | response = requests.post(f"https://{config['endpointAPI']}/1.0/order/cart/{cart.get('cartId')}/item/{itemID}/configuration", headers=headers, data=json.dumps(entry))
61 | if response.status_code == 200:
62 | print(f"Setting {entry}")
63 | else:
64 | print(response.status_code)
65 | print(json.dumps(response.json(), indent=4))
66 | exit()
67 | #set options
68 | options = [{'itemId':itemID,'duration':'P1M','planCode':'bandwidth-100-included-ks','pricingMode':'default','quantity':1},
69 | {'itemId':itemID,'duration':'P1M','planCode':'noraid-1x1000sa-sk010','pricingMode':'default','quantity':1},
70 | {'itemId':itemID,'duration':'P1M','planCode':'ram-4g-sk010','pricingMode':'default','quantity':1}
71 | ]
72 | for option in options:
73 | response = requests.post(f"https://{config['endpointAPI']}/1.0/order/cart/{cart.get('cartId')}/eco/options", headers=headers, data=json.dumps(option))
74 | if response.status_code == 200:
75 | print(f"Setting {option}")
76 | else:
77 | print(response.status_code)
78 | print(json.dumps(response.json(), indent=4))
79 | exit()
80 | print("Package ready, waiting for stock")
81 | #the order expires in about 3 days, we create a new one after 2 days
82 | for check in range(17280):
83 | now = datetime.now()
84 | print(f'Run {check+1} {now.strftime("%H:%M:%S")}')
85 | #wait for stock
86 | response = requests.get('https://us.ovh.com/engine/apiv6/dedicated/server/datacenter/availabilities?excludeDatacenters=false&planCode=22sk010&server=22sk010')
87 | if response.status_code == 200:
88 | stock = response.json()
89 | score = 0
90 | for datacenter in stock[0]['datacenters']:
91 | #if datacenter['availability'] != "unavailable": score = score +1
92 | if datacenter['datacenter'] == "rbx":
93 | print(f'RBX {datacenter["availability"]}')
94 | if datacenter['availability'] != "unavailable": score = score +1
95 | if datacenter['datacenter'] == "gra":
96 | print(f'GRA {datacenter["availability"]}')
97 | if datacenter['availability'] == "unavailable": score = score +1
98 | else:
99 | time.sleep(randint(5,10))
100 | continue
101 | #lets checkout boooyaaa
102 | #if score >= 1:
103 | if score == 2:
104 | #autopay should be set to true if you want automatic delivery, otherwise it will just generate a invoice
105 | payload={'autoPayWithPreferredPaymentMethod':False,'waiveRetractationPeriod':False}
106 | #prepare sig
107 | target = f"https://{config['endpointAPI']}/1.0/order/cart/{cart.get('cartId')}/checkout"
108 | now = str(int(time.time()) + timeDelta)
109 | signature = hashlib.sha1()
110 | signature.update("+".join([config['application_secret'], config['consumer_key'],'POST', target, json.dumps(payload), now]).encode('utf-8'))
111 | headers['X-Ovh-Signature'] = "$1$" + signature.hexdigest()
112 | headers['X-Ovh-Timestamp'] = now
113 | response = requests.post(target, headers=headers, data=json.dumps(payload))
114 | if response.status_code == 200:
115 | print(response.status_code)
116 | print(json.dumps(response.json(), indent=4))
117 | exit("Done")
118 | else:
119 | print("Got non 200 response code on checkout, retrying")
120 | continue
121 | time.sleep(10)
--------------------------------------------------------------------------------