|
| 1 | +import httpx |
| 2 | +import json |
| 3 | +import asyncio |
| 4 | +import re |
| 5 | +import logging |
| 6 | +import http.cookiejar as cookiejar |
| 7 | + |
| 8 | +gql_url = "https://gaming.amazon.com/graphql" |
| 9 | + |
| 10 | +logging.getLogger("httpx").setLevel(logging.WARNING) |
| 11 | +log = logging.getLogger() |
| 12 | +offers_payload = { |
| 13 | + "operationName": "OffersContext_Offers_And_Items", |
| 14 | + "variables": {"pageSize": 999}, |
| 15 | + "extensions": {}, |
| 16 | + "query": "query OffersContext_Offers_And_Items($dateOverride: Time, $pageSize: Int) {\n inGameLoot: items(\n collectionType: LOOT\n dateOverride: $dateOverride\n pageSize: $pageSize\n ) {\n items {\n ...Item\n __typename\n }\n __typename\n }\n}\n\nfragment Item on Item {\n id\n isDirectEntitlement\n requiresLinkBeforeClaim\n grantsCode\n isDeepLink\n isFGWP\n offers {\n ...Item_Offer\n __typename\n }\n game {\n ...Game\n __typename\n }\n __typename\n}\n\n\nfragment Item_Offer on Offer {\n id\n offerSelfConnection {\n eligibility {\n ...Item_Offer_Eligibility\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment Item_Offer_Eligibility on OfferEligibility {\n isClaimed\n canClaim\n missingRequiredAccountLink\n}\n\nfragment Game on GameV2 {\n id\n assets {\n title\n publisher\n }\n}\n", |
| 17 | +} |
| 18 | + |
| 19 | + |
| 20 | +async def claim_offer(offer_id: str, item: dict, client: httpx.AsyncClient, headers: dict) -> True: |
| 21 | + if item["offers"][0]["offerSelfConnection"]["eligibility"]["isClaimed"] != True: |
| 22 | + if ( |
| 23 | + item["offers"][0]["offerSelfConnection"]["eligibility"]["canClaim"] == False |
| 24 | + and item["offers"][0]["offerSelfConnection"]["eligibility"]["missingRequiredAccountLink"] == True |
| 25 | + ): |
| 26 | + log.error(f"Cannot collect game `{item['game']['assets']['title']}`, account link required.") |
| 27 | + return |
| 28 | + log.info(f"Collecting offer for {item['game']['assets']['title']}") |
| 29 | + claim_payload = { |
| 30 | + "operationName": "placeOrdersDetailPage", |
| 31 | + "variables": { |
| 32 | + "input": { |
| 33 | + "offerIds": [offer_id], |
| 34 | + "attributionChannel": '{"eventId":"ItemDetailRootPage:' + offer_id + '","page":"ItemDetailPage"}', |
| 35 | + } |
| 36 | + }, |
| 37 | + "extensions": {}, |
| 38 | + "query": "fragment Place_Orders_Payload_Order_Information on OfferOrderInformation {\n catalogOfferId\n claimCode\n entitledAccountId\n entitledAccountName\n id\n orderDate\n orderState\n __typename\n}\n\nmutation placeOrdersDetailPage($input: PlaceOrdersInput!) {\n placeOrders(input: $input) {\n error {\n code\n __typename\n }\n orderInformation {\n ...Place_Orders_Payload_Order_Information\n __typename\n }\n __typename\n }\n}\n", |
| 39 | + } |
| 40 | + |
| 41 | + response = await client.post(gql_url, headers=headers, data=json.dumps(claim_payload)) |
| 42 | + if response.json()["data"]["placeOrders"]["error"] != None: |
| 43 | + log.error(f"Error: {response.json()['data']['placeOrders']['error']}") |
| 44 | + |
| 45 | + |
| 46 | +async def primelooter(cookie_file): |
| 47 | + jar = cookiejar.MozillaCookieJar(cookie_file) |
| 48 | + jar.load() |
| 49 | + async with httpx.AsyncClient() as client: |
| 50 | + base_headers = { |
| 51 | + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0", |
| 52 | + } |
| 53 | + |
| 54 | + json_headers = base_headers | { |
| 55 | + "Content-Type": "application/json", |
| 56 | + } |
| 57 | + for _c in jar: |
| 58 | + client.cookies.jar.set_cookie(_c) |
| 59 | + |
| 60 | + html_body = (await client.get("https://gaming.amazon.com/home", headers=base_headers)).text |
| 61 | + matches = re.findall(r"name='csrf-key' value='(.*)'", html_body) |
| 62 | + json_headers["csrf-token"] = matches[0] |
| 63 | + |
| 64 | + response = await client.post(gql_url, headers=json_headers, data=json.dumps(offers_payload)) |
| 65 | + data = response.json()["data"]["inGameLoot"]["items"] |
| 66 | + |
| 67 | + coros = await asyncio.gather( |
| 68 | + *[claim_offer(item["offers"][0]["id"], item, client, json_headers) for item in data] |
| 69 | + ) |
0 commit comments