Merge pull request #489 from vogler/eg-mobile

eg: claim mobile games, closes #474
This commit is contained in:
Ralf Vogler 2025-06-05 18:19:22 +02:00 committed by GitHub
commit 90b3a93424
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 0 deletions

View file

@ -6,6 +6,7 @@ import path from 'path';
import { existsSync, writeFileSync } from 'fs'; import { existsSync, writeFileSync } from 'fs';
import { resolve, jsonDb, datetime, filenamify, prompt, confirm, notify, html_game_list, handleSIGINT } from './src/util.js'; import { resolve, jsonDb, datetime, filenamify, prompt, confirm, notify, html_game_list, handleSIGINT } from './src/util.js';
import { cfg } from './src/config.js'; import { cfg } from './src/config.js';
import { getGames } from './src/epic-games-mobile.js';
const screenshot = (...a) => resolve(cfg.dir.screenshots, 'epic-games', ...a); const screenshot = (...a) => resolve(cfg.dir.screenshots, 'epic-games', ...a);
@ -146,6 +147,15 @@ try {
// i.e. filter data.Catalog.searchStore.elements for .promotions.promotionalOffers being set and build URL with .catalogNs.mappings[0].pageSlug or .urlSlug if not set to some wrong id like it was the case for spirit-of-the-north-f58a66 - this is also what's done here: https://github.com/claabs/epicgames-freegames-node/blob/938a9653ffd08b8284ea32cf01ac8727d25c5d4c/src/puppet/free-games.ts#L138-L213 // i.e. filter data.Catalog.searchStore.elements for .promotions.promotionalOffers being set and build URL with .catalogNs.mappings[0].pageSlug or .urlSlug if not set to some wrong id like it was the case for spirit-of-the-north-f58a66 - this is also what's done here: https://github.com/claabs/epicgames-freegames-node/blob/938a9653ffd08b8284ea32cf01ac8727d25c5d4c/src/puppet/free-games.ts#L138-L213
const urlSlugs = await Promise.all((await game_loc.all()).map(a => a.getAttribute('href'))); const urlSlugs = await Promise.all((await game_loc.all()).map(a => a.getAttribute('href')));
const urls = urlSlugs.map(s => 'https://store.epicgames.com' + s); const urls = urlSlugs.map(s => 'https://store.epicgames.com' + s);
// Free mobile games - https://github.com/vogler/free-games-claimer/issues/474
// https://egs-platform-service.store.epicgames.com/api/v2/public/discover/home?count=10&country=DE&locale=en&platform=android&start=0&store=EGS
if (cfg.eg_mobile) {
console.log('Including mobile games...');
const mobileGames = await getGames();
urls.push(...mobileGames.map(x => x.url));
}
console.log('Free games:', urls); console.log('Free games:', urls);
for (const url of urls) { for (const url of urls) {

View file

@ -34,6 +34,7 @@ export const cfg = {
eg_password: process.env.EG_PASSWORD || process.env.PASSWORD, eg_password: process.env.EG_PASSWORD || process.env.PASSWORD,
eg_otpkey: process.env.EG_OTPKEY, eg_otpkey: process.env.EG_OTPKEY,
eg_parentalpin: process.env.EG_PARENTALPIN, eg_parentalpin: process.env.EG_PARENTALPIN,
eg_mobile: process.env.EG_MOBILE != '0', // claim mobile games
// auth prime-gaming // auth prime-gaming
pg_email: process.env.PG_EMAIL || process.env.EMAIL, pg_email: process.env.PG_EMAIL || process.env.EMAIL,
pg_password: process.env.PG_PASSWORD || process.env.PASSWORD, pg_password: process.env.PG_PASSWORD || process.env.PASSWORD,

51
src/epic-games-mobile.js Normal file
View file

@ -0,0 +1,51 @@
// following https://github.com/vogler/free-games-claimer/issues/474
const get = async (platform = 'android') => { // or ios
const r = await fetch(`https://egs-platform-service.store.epicgames.com/api/v2/public/discover/home?count=10&country=DE&locale=en&platform=${platform}&start=0&store=EGS`);
return await r.json();
};
// $ jq '.data[].topicId' -r
// $ jq '.data[] | {topicId,type} | flatten | @tsv' -r
// mobile-android-carousel featured
// mobile-android-featured-breaker featured
// mobile-android-genre-must-play interactiveIconList
// mobile-android-1pp featured
// mobile-android-fn-exp imageOnly
// android-mega-sale interactiveIconList
// mobile-android-free-game freeGame
// mobile-android-genre-action featured
// mobile-android-genre-free interactiveIconList
// mobile-android-genre-paid interactiveIconList
// $ jq '.data[].offers[].content | {slug: .mapping.slug, price: (.purchase[] | {decimal: .price.decimalPrice, type: .purchaseType})}'
// {
// "slug": "dc-heroes-united-android-de4bc2",
// "price": {
// "decimal": 0,
// "type": "Claim"
// }
// }
// {
// "slug": "ashworld-android-abd8de",
// "price": {
// "decimal": 4.79,
// "type": "Purchase"
// }
// }
const url = s => `https://store.epicgames.com/en-US/p/${s}`;
export const getPlatformGames = async platform => {
const json = await get(platform);
const free_game = json.data.filter(x => x.type == 'freeGame')[0];
// console.log(free_game);
return free_game.offers.map(offer => {
const c = offer.content;
// console.log(c.purchase)
return { title: c.title, url: url(c.mapping.slug) };
});
};
export const getGames = async () => [...await getPlatformGames('android'), ...await getPlatformGames('ios')];
// console.log(await getGames());