Skip to content

Commit 137ef4c

Browse files
Add GOG_CHECK_GP
1 parent 97547bb commit 137ef4c

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ Available options/variables and their default values:
108108
| GOG_EMAIL | | GOG email for login. Overrides EMAIL. |
109109
| GOG_PASSWORD | | GOG password for login. Overrides PASSWORD. |
110110
| GOG_NEWSLETTER | 0 | Do not unsubscribe from newsletter after claiming a game if 1. |
111+
| GOG_CHECK_GP | 0 | Check GamerPower API before opening browser. Exits early if no unclaimed giveaways. |
111112
| LG_EMAIL | | Legacy Games: email to use for redeeming (if not set, defaults to PG_EMAIL). |
112113

113114
See `src/config.js` for all options.

gog.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,61 @@ import { chromium } from 'patchright';
33
import chalk from 'chalk';
44
import { resolve, jsonDb, datetime, filenamify, prompt, confirm, notify, html_game_list, handleSIGINT } from './src/util.js';
55
import { cfg } from './src/config.js';
6+
import { gpUrlToStoreUrls } from './src/gp.js';
67

78
const screenshot = (...a) => resolve(cfg.dir.screenshots, 'gog', ...a);
89

910
const URL_CLAIM = 'https://www.gog.com/en';
11+
const GAMERPOWER_API_URL = 'https://www.gamerpower.com/api/giveaways?platform=gog&type=game';
1012

1113
console.log(datetime(), 'started checking gog');
1214

1315
const db = await jsonDb('gog.json', {});
1416

17+
function isGpGameAlreadyClaimed(storeUrl) {
18+
// GOG URLs look like: https://www.gog.com/en/game/game-name
19+
const match = storeUrl.match(/\/game\/([^/?]+)/);
20+
const game_id = match ? match[1] : storeUrl.split('/').pop();
21+
22+
// Check if any user has claimed this game (GOG db uses title as key)
23+
for (const [username, games] of Object.entries(db.data)) {
24+
for (const [title, info] of Object.entries(games)) {
25+
if (info.url?.includes(game_id) && (info.status === 'claimed' || info.status === 'existed')) {
26+
console.log(`[GamerPower] Already claimed by ${username}: ${storeUrl}`);
27+
return true;
28+
}
29+
}
30+
}
31+
32+
return false;
33+
}
34+
35+
async function getUnclaimedGpUrls() {
36+
if (!cfg.gog_check_gp) return [];
37+
38+
// gpUrlToStoreUrls handles fetching API and resolving URLs (opens browser only if needed)
39+
const allGpGames = await gpUrlToStoreUrls(GAMERPOWER_API_URL);
40+
41+
// Filter to GOG store URLs only
42+
const gogGames = allGpGames.filter(g => g.storeUrl.includes('gog.com'));
43+
console.log(`[GamerPower] ${gogGames.length} GOG store URLs`);
44+
45+
// Filter out already claimed games
46+
const unclaimed = gogGames.filter(g => !isGpGameAlreadyClaimed(g.storeUrl));
47+
console.log(`[GamerPower] ${unclaimed.length} unclaimed games`);
48+
49+
return unclaimed.map(g => g.storeUrl);
50+
}
51+
52+
// Check GamerPower first (before starting browser)
53+
const gpUrls = await getUnclaimedGpUrls();
54+
55+
// If GOG_CHECK_GP is enabled and no unclaimed games, exit early without opening browser
56+
if (cfg.gog_check_gp && gpUrls.length === 0) {
57+
console.log('No unclaimed GamerPower giveaways. Exiting.');
58+
process.exit(0);
59+
}
60+
1561
if (cfg.width < 1280) { // otherwise 'Sign in' and #menuUsername are hidden (but attached to DOM), see https://github.com/vogler/free-games-claimer/issues/335
1662
console.error(`Window width is set to ${cfg.width} but needs to be at least 1280 for GOG!`);
1763
process.exit(1);
@@ -117,6 +163,24 @@ try {
117163
const title = match_all[1] ? match_all[1] : match_all[2];
118164
const url = await banner.locator('a').first().getAttribute('href');
119165
console.log(`Current free game: ${chalk.blue(title)} - ${url}`);
166+
167+
// GamerPower games - verify they are included in the current giveaway
168+
if (cfg.gog_check_gp && gpUrls.length > 0) {
169+
console.log(`Verifying ${gpUrls.length} GamerPower giveaways match GOG's current giveaway...`);
170+
for (const gpUrl of gpUrls) {
171+
// Normalize URLs for comparison (extract game slug)
172+
const gpMatch = gpUrl.match(/\/game\/([^/?]+)/);
173+
const gpSlug = gpMatch ? gpMatch[1] : gpUrl.split('/').pop();
174+
const found = url && url.includes(gpSlug);
175+
if (!found) {
176+
console.error(`[GamerPower] ERROR: ${gpUrl} does NOT match GOG's current giveaway!`);
177+
console.error(`[GamerPower] GOG's current giveaway: ${url}`);
178+
} else {
179+
console.log(`[GamerPower] OK: ${gpUrl}`);
180+
}
181+
}
182+
}
183+
120184
db.data[user][title] ||= { title, time: datetime(), url };
121185
if (cfg.dryrun) process.exit(1);
122186
if (cfg.interactive && !await confirm()) process.exit(0);

src/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export const cfg = {
4444
gog_email: process.env.GOG_EMAIL || process.env.EMAIL,
4545
gog_password: process.env.GOG_PASSWORD || process.env.PASSWORD,
4646
gog_newsletter: process.env.GOG_NEWSLETTER == '1', // do not unsubscribe from newsletter after claiming a game
47+
gog_check_gp: process.env.GOG_CHECK_GP == '1', // check GamerPower for free GOG games
48+
4749
// auth AliExpress
4850
ae_email: process.env.AE_EMAIL || process.env.EMAIL,
4951
ae_password: process.env.AE_PASSWORD || process.env.PASSWORD,

0 commit comments

Comments
 (0)