Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epic: use data from JSON API for purchase URL #127

Closed
WiLuX-Source opened this issue Apr 20, 2023 · 33 comments · May be fixed by #130
Closed

Epic: use data from JSON API for purchase URL #127

WiLuX-Source opened this issue Apr 20, 2023 · 33 comments · May be fixed by #130
Labels
feature New feature or request store: epic-games

Comments

@WiLuX-Source
Copy link

parse freebies with https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions
and put them in a order with a url.
example would be like this

It will make code more future proof.

so it is like creating a url with "store.epicgames.com/purchase?offers=1-{namespace}-{id}

With this way we only handle Authentication with Playwright & Claim it with 1 simple button click.

@vogler
Copy link
Owner

vogler commented Apr 27, 2023

image
I assume the error is due to the fact that I already owned 'Never Alone'.
So, we'd need to only add those games to the URL which haven't been claimed yet.
I already parsed this json to get the current free games in #30, however, checking the order history with cookies alone somehow didn't work. Could try it with Playwright.

@WiLuX-Source
Copy link
Author

we can just visit game pages for checking whether if its claimed or not.

@vogler
Copy link
Owner

vogler commented Apr 27, 2023

Then there's no real advantage since you'd also have to deal with issues like #120 when you check the page for each game.

@vogler vogler added feature New feature or request store: epic-games labels Apr 27, 2023
@WiLuX-Source
Copy link
Author

Currently you get links through ui you click buttons. API takes time to change and most of the time not preffered. But game links and even /free-games can change overtime so we have that advantage if we go this route. We can also try claiming 1 by 1 and tell the user we couldn't claim. But to keep details i suggested visiting game page.

@vogler
Copy link
Owner

vogler commented Apr 27, 2023

We can play around a bit. I just want to avoid adding more code / situations that complicate debugging / lead to more captchas without a clear advantage (like not checking each game page).
In #30 there were some comments on alternatives.

@vogler
Copy link
Owner

vogler commented Apr 27, 2023

Didn't notice any requests to their API whether a game is claimed or not.
Seems like it's checked in a local database in the browser that contains all owned games:
image

@vogler
Copy link
Owner

vogler commented Apr 27, 2023

Check the PR. I'm always getting a captcha with it, even with a new IP.
Using the purchase URL like in your example seems to be problematic.

@WiLuX-Source
Copy link
Author

Strange I dont get any captchas with it.

@WiLuX-Source
Copy link
Author

Maybe another person can confirm if they get one?

@vogler
Copy link
Owner

vogler commented Apr 29, 2023

Did you run the code from the PR?
image

@WiLuX-Source
Copy link
Author

I didn't test it will let you know when i do it.

@vogler
Copy link
Owner

vogler commented May 4, 2023

Ok, just got no captcha with #130. However, missing the response, seems like it was just a blank page afterwards.

@WiLuX-Source
Copy link
Author

Yes, The blank page is the end result but It shows thanks for your order for a little bit of time. I'm sure we can capture that by waiting a text just like we did with Thanks for your order.

@WiLuX-Source
Copy link
Author

It might be Thanks for your purchase I don't really remember well.

@raulvasquez
Copy link

https://github.com/AuroPick/epic-free-games I noticed this repository, not sure if it would helpful vs the current method.

@WiLuX-Source
Copy link
Author

@raulvasquez It can help for listing the game through api and the guy went through the effort and added all of the country codes as well. But still not solving our current problem.

@vogler
Copy link
Owner

vogler commented May 11, 2023

@raulvasquez Thanks, I added an option EG_COUNTRY in 47be85f (via). I assume country should be enough to get the correct free games for the account's country and locale just changes the language of the description texts. Will have to wait until there is some difference (however, that is seldomly the case for DE vs. US).

@vogler
Copy link
Owner

vogler commented May 11, 2023

Using PWDEBUG=1 makes it show a captcha. Without it, you can't easily check what's going on, but looks like there really is just an empty page without any Thanks ....
I then used the new RECORD=1 and checked the .har in Chrome.
image
This request response looks like something to wait for.

{
  "cardinalInfo": null,
  "cardinalLookUpResponse": null,
  "confirmation": "F...",
  "message": null,
  "orderPending": null,
  "receiptResponse": {
    "orderId": "F...",
    "totalPrice": 0,
    "formattedTotalPrice": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "formattedCouponDiscount": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "formattedConvenienceFee": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "taxSettings": {},
    "orderStatus": "COMPLETED",
    "type": "PURCHASE",
    "formattedPresentmentAmount": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "totalTax": 0,
    "formattedPromotionDiscount": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "salesChannelId": "epic-store-web-purchase",
    "promotionDiscount": 0,
    "rewardDiscount": 0,
    "totalDiscounted": 0,
    "currency": "EUR",
    "sumPromotions": 0,
    "id": "QUICK_PURCHASE",
    "formattedSumPromotions": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "formattedTotalTax": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "rewardVoucher": null,
    "taxType": "",
    "formattedRewardDiscount": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "purchaseOrderPriceSummary": {
      "orderPrice": { "amount": 0, "currency": "EUR" },
      "purchasePrice": {
        "convenienceFee": { "amount": 0, "currency": "EUR" },
        "discountedPrice": { "amount": 0, "currency": "EUR" },
        "totalPrice": { "amount": 0, "currency": "EUR" }
      },
      "paymentAmount": { "amount": 0, "currency": "EUR" }
    },
    "paymentCurrencyCode": "EUR",
    "paymentCurrencyAmount": 0,
    "lineOffers": [
      {
        "quantity": 1,
        "entitlementSource": "AppEpicgamesCom",
        "formattedVoucherPrice": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
        "voucherDiscount": 0,
        "formattedBasePrice": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
        "offerIdx": 1,
        "sellerId": "o-rlswgtffm6ua68662gd37xv3lmq95q",
        "rewardDiscount": 0,
        "formattedDiscountedPrice": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
        "discountedPrice": 0,
        "price": {
          "convenienceFee": { "amount": 0, "currency": "EUR" },
          "discountedPrice": { "amount": 0, "currency": "EUR" },
          "totalPrice": { "amount": 0, "currency": "EUR" },
          "revenueWithoutTax": { "amount": 0, "currency": "USD" },
          "basePayout": { "amount": 0, "currency": "USD" },
          "basePrice": { "amount": 0, "currency": "EUR" }
        },
        "namespace": "676a89b2e8344c9db39a79724150cba6",
        "offerId": "5b99274688e9465aa9d5ca5cea176cfd",
        "basePrice": 0
      }
    ],
    "merchantGroup": "EGS_MKT",
    "voucherDiscount": 0,
    "convenienceFee": 0,
    "identityId": "...",
    "redeemRewardAmount": 0,
    "formattedTotalDiscounted": { "amount": "0.00", "symbol": "", "placement": "f", "decimals": 2, "digits": 2 },
    "status": "COMPLETED",
    "morId": "...",
    "xEpicEnv": "PUBLIC"
  },
  "syncToken": null
}

@WiLuX-Source
Copy link
Author

Page should say Thank you... then it should dissappear leaving you with blank page

@vogler
Copy link
Owner

vogler commented May 18, 2023

Page should say Thank you... then it should dissappear leaving you with blank page

I'm just getting a blank page:
https://github.com/vogler/free-games-claimer/assets/493741/ad0889f0-0bc2-499f-aa3d-c2f9cb57ba7b

However, waiting for the response above (see 3292257) works.

@vogler
Copy link
Owner

vogler commented May 18, 2023

So far, #130 saves one click() and still needs testing of the open points.

@WiLuX-Source
Copy link
Author

I will be busy for a month sorry. I'm currently in another place and can't test it right away.

@WiLuX-Source
Copy link
Author

Will keep you updated when i get on this.

@vogler
Copy link
Owner

vogler commented May 25, 2023

4e8e8ee URL construction somehow not reliable.

@vogler
Copy link
Owner

vogler commented May 25, 2023

Tried #130 for Death Stranding on a sep. account and it failed:
image

Current free game: DEATH STRANDING
  Not in library yet! Claim!
Unexpected confirm-order response. Message: We could not confirm your purchase at this time.  Please try again later.
{
  error: true,
  errorCode: null,
  message: 'We could not confirm your purchase at this time.  Please try again later.',
  messageVars: null,
  order: null,
  syncToken: '...'
}

@vogler
Copy link
Owner

vogler commented May 25, 2023

Changed to main branch:

  1. Device not supported -> Continue
  2. EPIC GAMES STORE END USER LICENSE AGREEMENT
    image

// Accept End User License Agreement (only needed once)
page.locator('input#agree').waitFor().then(async () => {
console.log('Accept End User License Agreement (only needed once)');
await page.locator('input#agree').check();
await page.locator('button:has-text("Accept")').click();
}).catch(_ => { });

Does not appear when using #130 which may be another issue.

However, that was not the problem and the issue persists.
Worked fine on main branch:

Free games: [ 'https://store.epicgames.com/en-US/p/death-stranding' ]
Current free game: DEATH STRANDING
  Not in library yet! Click GET.
  Claimed successfully!

@WiLuX-Source
Copy link
Author

Well then we might only use the parse current free games with api and do the claiming with normally. I'm still busy and didn't try.

@vogler
Copy link
Owner

vogler commented Jun 1, 2023

#130 loads https://store.epicgames.com/purchase?offers=1-d5241c76f178492ea1540fce45616757-b951f31da58449cd83d6cb1f4ca62d3a

Free games: [
  'Fallout: New Vegas - Ultimate Edition - https://store.epicgames.com/p/fallout-new-vegas--ultimate-edition'
]
Signed in as ...
  This game contains mature content recommended only for ages 18+
Current free game: Fallout: New Vegas - Ultimate Edition
  Not in library yet! Claim!
  purchaseURL: https://store.epicgames.com/purchase?offers=1-d5241c76f178492ea1540fce45616757-b951f31da58449cd83d6cb1f4ca62d3a
Unexpected confirm-order response. Message: We could not confirm your purchase at this time.  Please try again later.
{
  error: true,
  errorCode: null,
  message: 'We could not confirm your purchase at this time.  Please try again later.',
  messageVars: null,
  order: null,
  syncToken: '...'
}

image
vs. main branch which loads https://store.epicgames.com/purchase?highlightColor=0078f2&offers=1-3428aaab2c674c98b3acb789dcfaa548-08834851d4a54f48b485e97caab98012&orderId&purchaseToken&showNavigation=true:
image

However, those namespace/id values don't appear in the loaded https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale=en-US&country=DE&allowCountries=DE

vogler added a commit that referenced this issue Jun 1, 2023
@vogler
Copy link
Owner

vogler commented Jun 1, 2023

Same problem for Midnight Ghost Hunt - https://store.epicgames.com/p/midnight-ghost-hunt:
https://store.epicgames.com/purchase?offers=1-d5241c76f178492ea1540fce45616757-9d5d8c66d58e412286a3f98139657ef4
https://store.epicgames.com/purchase?highlightColor=0078f2&offers=1-964f58c4c2074404bf9c359483ab1a48-0613000f1d164fc1b5dd3e5ad1376399&orderId&purchaseToken&showNavigation=true

Unsuprisingly, https://github.com/AuroPick/epic-free-games also doesn't help here:

{
  currentGames: [
    {
      title: 'Midnight Ghost Hunt',
      id: '9d5d8c66d58e412286a3f98139657ef4',
      namespace: 'd5241c76f178492ea1540fce45616757',
      description: 'A chaotic multiplayer hide-and-seek game. Possess seemingly harmless objects as Ghosts or chase them down as Hunters before the clock strikes midnight!',
      effectiveDate: '2099-01-01T00:00:00.000Z',
      offerType: 'OTHERS',
      expiryDate: null,
      viewableDate: '2023-05-25T14:25:00.000Z',
      status: 'ACTIVE',
      isCodeRedemptionOnly: true,
      keyImages: [Array],
      seller: [Object],
      productSlug: 'midnight-ghost-hunt',
      urlSlug: 'mystery-game-5',
      url: null,
      items: [Array],
      customAttributes: [Array],
      categories: [Array],
      tags: [],
      catalogNs: [Object],
      offerMappings: [],
      price: [Object],
      promotions: [Object]
    }
  ],
}

To get the correct namespace/id, one needs apparently to make two extra requests to their GraphQL API:

  1. https://store.epicgames.com/graphql?operationName=getMappingByPageSlug&variables=%7B%22pageSlug%22:%22midnight-ghost-hunt%22,%22locale%22:%22en-US%22%7D&extensions=%7B%22persistedQuery%22:%7B%22version%22:1,%22sha256Hash%22:%22781fd69ec8116125fa8dc245c0838198cdf5283e31647d08dfa27f45ee8b1f30%22%7D%7D only gives sandboxId which is the same as namespace
  2. https://store.epicgames.com/graphql?operationName=getCatalogOffer&variables=%7B%22locale%22:%22en-US%22,%22country%22:%22DE%22,%22offerId%22:%220613000f1d164fc1b5dd3e5ad1376399%22,%22sandboxId%22:%22964f58c4c2074404bf9c359483ab1a48%22%7D&extensions=%7B%22persistedQuery%22:%7B%22version%22:1,%22sha256Hash%22:%226797fe39bfac0e6ea1c5fce0ecbff58684157595fee77e446b4254ec45ee2dcb%22%7D%7D which will also give the correct id:
    image

@WiLuX-Source
Copy link
Author

Hello there still away from my main pc,

What I can say is the safest bet would be parse games with json and do the rest of the things normally it is only a small boost but we'll get what we can get.

@vogler
Copy link
Owner

vogler commented Jun 6, 2023

See above. You can base a PR on what I made. I think I won't spent time on it since it's too much brittle code for little gain.

@vogler
Copy link
Owner

vogler commented Jul 13, 2023

@WiLuX-Source Any update? If not, I'll close this.

@WiLuX-Source
Copy link
Author

@vogler you can close this issue we can discuss further when i make pr.

@vogler vogler changed the title Make use of APIs in Epic Freebies. Epic: use data from JSON API for purchase URL Dec 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request store: epic-games
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants