Skip to content

Commit c12675c

Browse files
committed
V1.5.0
1 parent 0eecf53 commit c12675c

File tree

10 files changed

+126
-194
lines changed

10 files changed

+126
-194
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 4
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

.eslintrc.json

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
{
22
"env": {
3-
"browser": true,
43
"node": true,
5-
"es6": true
4+
"es6": true,
5+
"es2017": true,
6+
"es2020": true,
7+
"es2021": true
68
},
79
"extends": "eslint:recommended",
10+
"parser": "@babel/eslint-parser",
811
"parserOptions": {
9-
"ecmaVersion": 2018
12+
"requireConfigFile": false
1013
},
1114
"rules": {
1215
"accessor-pairs": "error",
13-
"array-bracket-newline": ["error", "consistent"],
16+
"array-bracket-newline": ["error", { "multiline": true }],
1417
"array-bracket-spacing": ["error", "never", { "arraysInArrays": true }],
1518
"array-callback-return": "error",
16-
"array-element-newline": ["error", "consistent"],
19+
"array-element-newline": ["error", {
20+
"ArrayExpression": "consistent",
21+
"ArrayPattern": { "multiline": true }
22+
}],
1723
"arrow-body-style": "error",
18-
"arrow-parens": ["error", "as-needed"],
24+
"arrow-parens": "error",
1925
"arrow-spacing": "error",
2026
"block-scoped-var": "error",
2127
"block-spacing": "error",
2228
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
2329
"camelcase": "error",
2430
"class-methods-use-this": "error",
25-
"comma-dangle": ["error", "only-multiline"],
31+
"comma-dangle": ["error", "always-multiline"],
2632
"comma-spacing": "error",
2733
"comma-style": "error",
2834
"complexity": "error",
@@ -46,7 +52,7 @@
4652
"implicit-arrow-linebreak": "error",
4753
"indent": ["error", 4, { "SwitchCase": 1 }],
4854
"init-declarations": "error",
49-
"key-spacing": ["error", { "mode": "minimum", "align": "value" }],
55+
"key-spacing": ["error", { "align": "value" }],
5056
"keyword-spacing": "error",
5157
"linebreak-style": "error",
5258
"lines-between-class-members": ["error", "always"],
@@ -67,6 +73,7 @@
6773
"no-dupe-else-if": "error",
6874
"no-duplicate-imports": "error",
6975
"no-else-return": "error",
76+
"no-extra-parens": ["error", "all", { "nestedBinaryExpressions": false }],
7077
"no-empty-function": "error",
7178
"no-eq-null": "error",
7279
"no-eval": "error",
@@ -93,7 +100,6 @@
93100
"no-new-wrappers": "error",
94101
"no-octal": "error",
95102
"no-octal-escape": "error",
96-
"no-param-reassign": "error",
97103
"no-proto": "error",
98104
"no-redeclare": "error",
99105
"no-return-assign": "error",
@@ -122,7 +128,7 @@
122128
"no-with": "error",
123129
"no-whitespace-before-property": "error",
124130
"nonblock-statement-body-position": "error",
125-
"object-curly-newline": "error",
131+
"object-curly-newline": ["error", { "multiline": true }],
126132
"object-curly-spacing": ["error", "always"],
127133
"object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }],
128134
"object-shorthand": "error",
@@ -159,7 +165,6 @@
159165
"space-infix-ops": "error",
160166
"space-unary-ops": "error",
161167
"spaced-comment": "error",
162-
"strict": ["error", "global"],
163168
"switch-colon-spacing": "error",
164169
"symbol-description": "error",
165170
"template-curly-spacing": "error",
@@ -170,4 +175,4 @@
170175
"yield-star-spacing": "error",
171176
"yoda": "error"
172177
}
173-
}
178+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*.lnk
44
node_modules
55
package-lock.json
6+
DeviceAuthGenerator.exe
7+
device_auths.json
68
.egstore/*
79
.vscode/*
810
!.vscode/settings.json

.vscode/settings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"eslint.format.enable": true,
3+
"editor.formatOnSave": true,
4+
"eslint.alwaysShowStatus": true,
5+
"prettier.requireConfig": true,
6+
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
7+
"[javascript]": {
8+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
9+
}
10+
}

README.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,15 @@
55
Claim [available free game promotions](https://www.epicgames.com/store/free-games) from the Epic Game Store.
66

77
## Requirements
8+
* [DeviceAuthGenerator](https://github.com/xMistt/DeviceAuthGenerator)
89
* [Node.js](https://nodejs.org/download/)
910

10-
## Instructions (arguments)
11-
1. Download/clone repo
12-
3. Run `npm install`
13-
4. Run `npm start USERNAME PASSWORD 0|1 2FA_SECRET`*
14-
15-
## Instructions (config)
16-
1. Download/clone repo
11+
## Instructions
12+
1. Download/clone this repository
1713
2. Run `npm install`
18-
3. Edit `config.json` to include your EpicGames credentials and options
19-
4. Run `npm start`*
20-
21-
*Only this step is required after the initial use.
14+
3. Generate `device_auths.json` (using [DeviceAuthGenerator](https://github.com/xMistt/DeviceAuthGenerator))
15+
4. (Optional) Edit `config.json`
16+
5. Run `npm start`
2217

2318
## FAQ
2419
### Why should I use this?
@@ -28,10 +23,14 @@ Also, this is a good alternative, in case you don't like using Epic's client or
2823
### Why should I even bother claiming these free games?
2924
To which I will say, why not? Most of these games are actually outstanding games! Even if you don't like Epic and their shenanigans, you will be pleased to know that Epic actually funds all the free copies that are given away: ["But we actually found it was more economical to pay developers [a lump sum] to distribute their game free for two weeks..."](https://arstechnica.com/gaming/2019/03/epic-ceo-youre-going-to-see-lower-prices-on-epic-games-store/)
3025

31-
### Can I use the looping or multi-account feature when using launch arguments?
32-
No, these are only usable by using the config.
33-
3426
## Changelog
27+
### V1.5.0
28+
* Fixed login
29+
* Fixed purchase (claiming)
30+
* Removed ownership check (broken)
31+
* Removed unneeded dependencies
32+
* Code restyling
33+
3534
### V1.4.1
3635
* Removed the need for graphql query
3736

claimer.js

Lines changed: 16 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
"use strict";
2+
23
const { "Launcher": EpicGames } = require("epicgames-client");
4+
const { freeGamesPromotions } = require("./src/gamePromotions");
5+
6+
const Auths = require(`${__dirname}/device_auths.json`);
37
const CheckUpdate = require("check-update-github");
4-
const ClientLoginAdapter = require("epicgames-client-login-adapter");
58
const Config = require(`${__dirname}/config.json`);
69
const Logger = require("tracer").console(`${__dirname}/logger.js`);
710
const Package = require("./package.json");
8-
const TwoFactor = require("node-2fa");
9-
const Cookie = require('tough-cookie').Cookie;
10-
11-
const { freeGamesPromotions } = require('./src/gamePromotions');
1211

1312
function isUpToDate() {
1413
return new Promise((res, rej) => {
1514
CheckUpdate({
1615
"name": Package.name,
1716
"currentVersion": Package.version,
1817
"user": "revadike",
19-
"branch": "master"
18+
"branch": "master",
2019
}, (err, latestVersion) => {
2120
if (err) {
2221
rej(err);
@@ -27,116 +26,36 @@ function isUpToDate() {
2726
});
2827
}
2928

30-
function getChromeCookie(cookie) {
31-
cookie = Object.assign({}, cookie);
32-
cookie.name = cookie.key;
33-
if (cookie.expires instanceof Date) {
34-
cookie.expires = cookie.expires.getTime() / 1000.0;
35-
} else {
36-
delete cookie.expires;
37-
}
38-
return cookie;
39-
}
40-
41-
function getToughCookie(cookie) {
42-
cookie = Object.assign({}, cookie);
43-
cookie.key = cookie.name;
44-
cookie.expires = new Date(cookie.expires * 1000);
45-
return new Cookie(cookie);
29+
function sleep(delay) {
30+
return new Promise((res) => setTimeout(res, delay * 60000));
4631
}
4732

4833
(async() => {
4934
if (!await isUpToDate()) {
5035
Logger.warn(`There is a new version available: ${Package.url}`);
5136
}
5237

53-
let { accounts, options, delay, loop } = Config;
54-
if (!options) {
55-
options = {};
56-
}
57-
let sleep = delay => new Promise(res => setTimeout(res, delay * 60000));
38+
let { options, delay, loop } = Config;
5839
do {
59-
if (process.argv.length > 2) {
60-
loop = false;
61-
accounts = [{
62-
"email": process.argv[2],
63-
"password": process.argv[3],
64-
"rememberLastSession": Boolean(Number(process.argv[4])),
65-
"secret": process.argv[5],
66-
}];
67-
}
68-
69-
for (let account of accounts) {
70-
let noSecret = !account.secret || account.secret.length === 0;
71-
if (!noSecret) {
72-
let { token } = TwoFactor.generateToken(account.secret);
73-
account.twoFactorCode = token;
74-
}
75-
76-
let epicOptions = Object.assign({}, options);
77-
Object.assign(epicOptions, account);
78-
79-
let client = new EpicGames(epicOptions);
80-
40+
for (let email in Auths) {
41+
let useDeviceAuth = true;
42+
let clientOptions = { email, ...options };
43+
let client = new EpicGames(clientOptions);
8144
if (!await client.init()) {
8245
throw new Error("Error while initialize process.");
8346
}
8447

85-
let success = false;
86-
try {
87-
success = await client.login(account);
88-
} catch (error) {
89-
Logger.warn(error.message);
90-
}
91-
48+
let success = await client.login({ useDeviceAuth });
9249
if (!success) {
93-
Logger.warn(`Failed to login as ${client.config.email}, please attempt manually.`);
94-
95-
96-
if (account.rememberLastSession) {
97-
if (!options.cookies) {
98-
options.cookies = [];
99-
}
100-
if (account.cookies && account.cookies.length) {
101-
options.cookies = options.cookies.concat(account.cookies);
102-
}
103-
client.http.jar._jar.store.getAllCookies((err, cookies) => {
104-
for (const cookie of cookies) {
105-
options.cookies.push(getChromeCookie(cookie));
106-
}
107-
});
108-
}
109-
110-
let auth = await ClientLoginAdapter.init(account, options);
111-
let exchangeCode = await auth.getExchangeCode();
112-
113-
if (account.rememberLastSession) {
114-
let cookies = await auth.getPage().then(p => p.cookies());
115-
for (let cookie of cookies) {
116-
cookie = getToughCookie(cookie);
117-
client.http.jar.setCookie(cookie, "https://" + cookie.domain);
118-
}
119-
}
120-
121-
await auth.close();
122-
123-
if (!await client.login(null, exchangeCode)) {
124-
throw new Error("Error while logging in.");
125-
}
50+
throw new Error(`Failed to login as ${client.config.email}`);
12651
}
12752

12853
Logger.info(`Logged in as ${client.account.name} (${client.account.id})`);
12954

130-
let { country } = client.account.country;
55+
let { country } = client.account;
13156
let freePromos = await freeGamesPromotions(client, country, country);
13257

13358
for (let offer of freePromos) {
134-
let launcherQuery = await client.launcherQuery(offer.namespace, offer.id);
135-
if (launcherQuery.data.Launcher.entitledOfferItems.entitledToAllItemsInOffer) {
136-
Logger.info(`${offer.title} is already claimed for this account`);
137-
continue;
138-
}
139-
14059
try {
14160
let purchased = await client.purchase(offer, 1);
14261
if (purchased) {
@@ -167,7 +86,7 @@ function getToughCookie(cookie) {
16786
process.exit(0);
16887
}
16988
} while (loop);
170-
})().catch(err => {
89+
})().catch((err) => {
17190
Logger.error(err);
17291
process.exit(1);
17392
});

config.json

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,4 @@
11
{
2-
"accounts": [
3-
{
4-
"email": "YOUR_EMAIL1_HERE",
5-
"password": "YOUR_PASSWORD1_HERE",
6-
"secret": "YOUR_2FA_SECRET1_HERE_OR_EMPTY",
7-
"rememberLastSession": true
8-
},
9-
{
10-
"email": "YOUR_EMAIL2_HERE",
11-
"password": "YOUR_PASSWORD2_HERE",
12-
"secret": "YOUR_2FA_SECRET2_HERE_OR_EMPTY",
13-
"rememberLastSession": true,
14-
"cookies": []
15-
}
16-
],
172
"options": {},
183
"delay": 1440,
194
"loop": true

package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "epicgames-freebies-claimer",
3-
"version": "1.4.1",
3+
"version": "1.5.0",
44
"description": "Claim free game promotions from the Epic Game Store",
55
"author": {
66
"name": "Revadike",
@@ -28,16 +28,15 @@
2828
"homepage": "https://github.com/revadike/epicgames-freebies-claimer",
2929
"url": "https://github.com/revadike/epicgames-freebies-claimer",
3030
"devDependencies": {
31+
"@babel/eslint-parser": "latest",
3132
"chai": "*",
32-
"eslint": "^6.8.0",
33+
"eslint": "latest",
3334
"mocha": "*"
3435
},
3536
"dependencies": {
3637
"check-update-github": "^0.0.4",
3738
"colors": "^1.4.0",
3839
"epicgames-client": "Revadike/node-epicgames-client#develop",
39-
"epicgames-client-login-adapter": "Revadike/node-epicgames-client-login-adapter",
40-
"node-2fa": "^1.1.2",
4140
"tracer": "^1.0.3"
4241
}
4342
}

0 commit comments

Comments
 (0)