commit c3f44c64de60aef5b67e3e40c4f33ff768a16da8 Author: videogame hacker Date: Thu Aug 19 16:12:02 2021 +0100 Initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c6ab14f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0041fb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/README.md b/README.md new file mode 100644 index 0000000..f56b39d --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# shark radar + +where are the cuddlies at? (UK only :<) diff --git a/list.py b/list.py new file mode 100644 index 0000000..80c8003 --- /dev/null +++ b/list.py @@ -0,0 +1,90 @@ +import json +import colorama +import requests + +with open("stores.json") as f: + # Parsed from (search for "allStores=["): + # https://www.ikea.com/gb/en/products/javascripts/range-stockcheck.ebfce6584a37458deef3.js + stores = json.load(f) + + +def calculate_stock(availability): + store_id = availability["classUnitKey"]["classUnitCode"] + store_name = \ + [store["name"] for store in stores if store["value"] == store_id] + if len(store_name) < 1: + return None + + store_name = store_name[0] + + availability_info = availability["buyingOption"]["cashCarry"]["availability"] + quantity = int(availability_info["quantity"]) + + next_restock = None + if "restocks" in availability_info: + next_restock = availability_info["restocks"][0] + + return { + "store": store_name, + "quantity": quantity, + "next_restock": next_restock, + } + + +def pretty_print_stock(stock): + store = stock["store"] + quantity = stock["quantity"] + next_restock = stock["next_restock"] + + s = "" + if quantity > 0: + s += colorama.Fore.GREEN + else: + s += colorama.Fore.RED + s += store + s += colorama.Fore.RESET + s += " " + s += str(quantity) + + if next_restock is not None: + s += colorama.Fore.LIGHTBLACK_EX + s += " (restock of " + s += colorama.Fore.RESET + s += str(next_restock["quantity"]) + s += colorama.Fore.LIGHTBLACK_EX + s += " coming " + s += colorama.Fore.RESET + s += next_restock["earliestDate"] + s += " ~ " + s += next_restock["latestDate"] + s += colorama.Fore.LIGHTBLACK_EX + s += ")" + s += colorama.Fore.RESET + + print(s) + + +def main(): + colorama.init() + + print("Fetching BLÅHAJ listings…\n") + + availabilities = requests.get("https://api.ingka.ikea.com/cia/availabilities/ru/gb?itemNos=30373588&expand=StoresList,Restocks,SalesLocations", headers={ + "Accept": "application/json;version=2", + "X-Client-ID": "b6c117e5-ae61-4ef5-b4cc-e0b1e37f0631" + }) + availabilities = availabilities.json() + + sharks = [] + for availability in availabilities["availabilities"]: + stock = calculate_stock(availability) + if stock is None: + continue + sharks.append(stock) + sharks.sort(key=lambda s: s["quantity"], reverse=True) + + for stock in sharks: + pretty_print_stock(stock) + + +main() diff --git a/stores.json b/stores.json new file mode 100644 index 0000000..df5289e --- /dev/null +++ b/stores.json @@ -0,0 +1,161 @@ +[ + { + "value": "113", + "name": "Belfast", + "storeAddress": { + "address": "Holywood Exchange, 306 Airport RD W", + "cityName": "Belfast" + } + }, + { + "value": "264", + "name": "Bristol", + "storeAddress": { + "address": "Eastgate Road, Eastville", + "cityName": "Bristol" + } + }, + { + "value": "267", + "name": "Cardiff", + "storeAddress": { + "address": "Ferry Road, Grangetown", + "cityName": "Cardiff" + } + }, + { + "value": "144", + "name": "Croydon", + "storeAddress": { + "address": "Access via Hesterman Way", + "cityName": "Croydon" + } + }, + { + "value": "548", + "name": "Exeter", + "storeAddress": { + "address": "1 IKEA WAY, off Newcourt Way", + "cityName": "Exeter" + } + }, + { + "value": "143", + "name": "Gateshead", + "storeAddress": { + "address": "Metro Park West", + "cityName": "Gateshead, Tyne & Wear" + } + }, + { + "value": "567", + "name": "Greenwich", + "storeAddress": { + "address": "55-57 Bugsby's Way", + "cityName": "London, Greenwich" + } + }, + { + "value": "261", + "name": "Leeds", + "storeAddress": { + "address": "Holden Ing Way", + "cityName": "Birstall, Batley" + } + }, + { + "value": "186", + "name": "Manchester", + "storeAddress": { + "address": "110 Wellington Road", + "cityName": "Greater Manchester" + } + }, + { + "value": "185", + "name": "Milton Keynes", + "storeAddress": { + "address": "Goslington, Off Bletcham Way", + "cityName": "Milton Keynes" + } + }, + { + "value": "263", + "name": "Nottingham", + "storeAddress": { + "address": "Ikea Way, Giltbrook", + "cityName": "Nottingham" + } + }, + { + "value": "461", + "name": "Reading", + "storeAddress": { + "address": "Pincents Kiln Industrial Pk, Theale", + "cityName": "Reading" + } + }, + { + "value": "519", + "name": "Sheffield", + "storeAddress": { "address": "Sheffield Road", "cityName": "Tinsley" } + }, + { + "value": "125", + "name": "Southampton", + "storeAddress": { + "address": "West Quay Road", + "cityName": "Southhampton" + } + }, + { + "value": "255", + "name": "Tottenham", + "storeAddress": { "address": "Glover Drive", "cityName": "Edmonton" } + }, + { + "value": "140", + "name": "Warrington", + "storeAddress": { + "address": "910 Europe Boulevard", + "cityName": "Warrington" + } + }, + { + "value": "266", + "name": "Glasgow", + "storeAddress": { + "address": "99 Kings Inch Drive", + "cityName": "Glasgow" + } + }, + { + "value": "265", + "name": "Edinburgh", + "storeAddress": { + "address": "Costkea way, Loanhead", + "cityName": "Edinburgh, Midlothian" + } + }, + { + "value": "262", + "name": "Lakeside", + "storeAddress": { + "address": "Heron Way, Lakeside", + "cityName": "Essex" + } + }, + { + "value": "142", + "name": "Birmingham", + "storeAddress": { + "address": "Park Lane, Wednesbury", + "cityName": "West Midlands" + } + }, + { + "value": "141", + "name": "Wembley", + "storeAddress": { "address": "2 Drury Way", "cityName": "London" } + } +]