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

fallback slug on offerMappings and catalogNs #51

Merged
merged 3 commits into from
Sep 25, 2022
Merged

Conversation

Purexo
Copy link
Contributor

@Purexo Purexo commented Sep 23, 2022

add description
add banner

J'ai fait pas mal de reverse-engeenering pour voir ce qu'on pouvais faire.
J'ai trouvé cette URL https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale=fr&country=FR&allowCountries=FR appelé depuis la page d'accueil

J'y ai trouvé les champs catalogNs et offerMappings qui avait le slug, alors que le productSlug était null.

Au passage j'ai rajouté la description et une bannière.

J'apprécierai que quelqu'un test, je suis sur un PC avec proxy d'entreprise, c'est galère de lancer des programmes node qui vont requêter l'exterieur.

@targos
Copy link
Member

targos commented Sep 23, 2022

Fixes #44 ?

@Purexo
Copy link
Contributor Author

Purexo commented Sep 23, 2022

effectivement c'est lié. je l'avais oublié ça m'aurait fait gagner du temps.

par contre, je n'ai pas remplacé, j'ai fait une chaine de fallback. Je ne sais pas comment c'est fichu en interne leur truc, mais parfois, il y a le productSlug, parfois pas. parfois il y a des productPage dans offerMappings parfois pas, idem pour catalogNs

La pour cette semaine :

  • Ark -> productSlug OK, catalogNs productPage OK, offerMapping KO
  • Gloomhaven -> productSlug KO, catalogNs productPage OK, offerMapping OK

@Purexo
Copy link
Contributor Author

Purexo commented Sep 23, 2022

Sur https://store-site-backend-static-ipv4.ak.epicgames.com/freeGamesPromotions?locale=fr&country=FR&allowCountries=FR

J'ai fais des petites stats :

┌─────────┬─────────────────────────────┬───────┐
│ (index) │            name             │ count │
├─────────┼─────────────────────────────┼───────┤
│    0    │           'total'           │  12   │
│    1    │        'productSlug'        │   8   │
│    2    │   'catalogNs productHome'   │  10   │
│    3    │ 'offerMappings productHome' │   4   │
│    4    │         'fallback'          │  12   │
└─────────┴─────────────────────────────┴───────┘
console.table([
  {name: 'total', count: elements.length},
  {name: 'productSlug', count: elements.filter(e => e.productSlug).length},
  {name: 'catalogNs productHome', count: elements.filter(
      e => e.catalogNs.mappings.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'offerMappings productHome', count: elements.filter(
      e => e.offerMappings.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'fallback', count: elements.filter(
      e => e.productSlug
        || e.catalogNs.mappings.find(m => m.pageType === 'productHome')
        || e.offerMappings.find(m => m.pageType === 'productHome')
    ).length},
])

@Purexo
Copy link
Contributor Author

Purexo commented Sep 23, 2022

J'ai fais la graphql query sans mettre freeGame: true, onSale: true

┌─────────┬─────────────────────────────┬───────┐
│ (index) │            name             │ count │
├─────────┼─────────────────────────────┼───────┤
│    0    │           'total'           │ 1000  │
│    1    │        'productSlug'        │  224  │
│    2    │   'catalogNs productHome'   │  827  │
│    3    │ 'offerMappings productHome' │  163  │
│    4    │         'fallback'          │  931  │
└─────────┴─────────────────────────────┴───────┘

931 / 1000, c'est pas fou mais je n'aurais pas mieux je pense.

Mais ça appuie que aucune des sources n'est sur, mais si on les combine on a plus de chance d'avoir un résultat.

Et dans le pire des cas, si on a pas le slug, je met l'url vers la page ou il y a les jeux offerts

src/crons/EpicGames.ts Outdated Show resolved Hide resolved
@Purexo
Copy link
Contributor Author

Purexo commented Sep 23, 2022

J'ai trouvé ça comme doc non-officiel. https://github.com/Tectors/EpicGraphQL/blob/main/docs/graphql/catalog/searchStoreQuery.graphql
Le urlSlug est parfois bon, parfois pas. (genre c'est un uuid qui marche pas comme slug). et le champ url à l'air tout le temps à null.

J'ai dig un peu pour le urlSlug, en ne prenant pas en compte ceux qui avaient une forme hexadécimal. Et en l'ajoutant en dernier fallback, Sur l'echantillon de 1000, tout les items ont leur slug !

Tout les items
┌─────────┬────────────────────────────────┬───────┐
│ (index) │              name              │ count │
├─────────┼────────────────────────────────┼───────┤
│    0    │            'total'             │ 1000  │
│    1    │         'productSlug'          │  224  │
│    2    │    'catalogNs productHome'     │  828  │
│    3    │  'offerMappings productHome'   │  163  │
│    4    │           'fallback'           │  932  │
│    5    │       'fallback urlSlug'       │ 1000  │
│    6    │  'urlSlug but no productSlug'  │  613  │
│    7    │   'urlSlug but no catalogNs'   │  172  │
│    8    │ 'urlSlug but no offerMappings' │  837  │
│    9    │           'url null'           │ 1000  │
└─────────┴────────────────────────────────┴───────┘

tout les items avec un urlSlug de forme hexadécimal
┌─────────┬─────────────────────────────┬───────┐
│ (index) │            name             │ count │
├─────────┼─────────────────────────────┼───────┤
│    0    │           'total'           │  163  │
│    1    │        'productSlug'        │   0   │
│    2    │   'catalogNs productHome'   │  163  │
│    3    │ 'offerMappings productHome' │  163  │
│    4    │         'fallback'          │  163  │
│    5    │         'url null'          │  163  │
└─────────┴─────────────────────────────┴───────┘
const response = require('./response.json');
elements = response.data.Catalog.searchStore.elements;

elements.sort((a, b) => a.title.localeCompare(b.title))

console.table([
  {name: 'total', count: elements.length},
  {name: 'productSlug', count: elements.filter(e => e.productSlug).length},
  {name: 'catalogNs productHome', count: elements.filter(
      e => e.catalogNs.mappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'offerMappings productHome', count: elements.filter(
      e => e.offerMappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'fallback', count: elements.filter(
      e => e.productSlug
        || e.catalogNs.mappings?.find(m => m.pageType === 'productHome')
        || e.offerMappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'fallback urlSlug', count: elements.filter(
      e => e.productSlug
        || e.catalogNs.mappings?.find(m => m.pageType === 'productHome')
        || e.offerMappings?.find(m => m.pageType === 'productHome')
        || (e.urlSlug && !/^[0-9a-f]+$/.test(e.urlSlug))
    ).length},
  {name: 'urlSlug but no productSlug', count: elements.filter(
      e => (e.urlSlug && !/^[0-9a-f]+$/.test(e.urlSlug)) && !e.productSlug
    ).length},
  {name: 'urlSlug but no catalogNs', count: elements.filter(
      e => (e.urlSlug && !/^[0-9a-f]+$/.test(e.urlSlug)) && !e.catalogNs.mappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'urlSlug but no offerMappings', count: elements.filter(
      e => (e.urlSlug && !/^[0-9a-f]+$/.test(e.urlSlug)) && !e.offerMappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'url null', count: elements.filter(e => !e.url).length},
]);

const badElementsUrlSlug = elements.filter(e => !e.urlSlug || /^[0-9a-f]+$/.test(e.urlSlug));

// console.table(badElementsUrlSlug, ['title', 'urlSlug']);
console.table([
  {name: 'total', count: badElementsUrlSlug.length},
  {name: 'productSlug', count: badElementsUrlSlug.filter(e => e.productSlug).length},
  {name: 'catalogNs productHome', count: badElementsUrlSlug.filter(
      e => e.catalogNs.mappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'offerMappings productHome', count: badElementsUrlSlug.filter(
      e => e.offerMappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'fallback', count: badElementsUrlSlug.filter(
      e => e.productSlug
        || e.catalogNs.mappings?.find(m => m.pageType === 'productHome')
        || e.offerMappings?.find(m => m.pageType === 'productHome')
    ).length},
  {name: 'url null', count: badElementsUrlSlug.filter(e => !e.url).length},
]);

J'avais loggé tout les slugs hexa, pas de faux positif évident sur l'échantillon

@Purexo
Copy link
Contributor Author

Purexo commented Sep 23, 2022

En vrai de vrai, mais flemme de check.
Le chemin de fallback le plus rapide devrait être urlSlug(non-hexa) -> catalogNs

@targos targos linked an issue Sep 23, 2022 that may be closed by this pull request
@Purexo
Copy link
Contributor Author

Purexo commented Sep 24, 2022

J'ai ajouté un cas de test sur getOfferedGames.
ça va appeler la méthode sur les 7 derniers jours (histoire d'avoir une correspondance malgré le filter de date qu'il y a dans la fonction)
Et vérifier la forme du retour (null ou tableau d'objet, la plupart des valeurs des objets étant des string non vide)

@Xstoudi
Copy link
Member

Xstoudi commented Sep 24, 2022

Ok pour moi, t'as encore des modifs à faire ou c'est mergeable ?

@Purexo
Copy link
Contributor Author

Purexo commented Sep 24, 2022

C'est ok pour moi, au pire je ferai une autre pr plus tard

@targos targos merged commit 92be6d7 into main Sep 25, 2022
@targos targos deleted the feature/fix-epic branch September 25, 2022 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Replace productSlug with pageSlug to generate free game URLs
3 participants