* Format and fix sonar issues

This commit is contained in:
4n4n4s 2023-11-10 16:43:47 +00:00
parent 16cb194216
commit 617229f659
3 changed files with 35 additions and 43 deletions

View file

@ -96,7 +96,7 @@ Available options/variables and their default values:
| STEAM_PASSWORD | | Steam password for login. Overrides PASSWORD. | | STEAM_PASSWORD | | Steam password for login. Overrides PASSWORD. |
| STEAM_JSON | 0 | Claims steam games from json. STEAM_JSON_URL can be defined. | | STEAM_JSON | 0 | Claims steam games from json. STEAM_JSON_URL can be defined. |
| STEAM_JSON_URL | [steam-games.json](https://raw.githubusercontent.com/vogler/free-games-claimer/main/steam-games.json) | A list of steam urls in json format to claim the games. | | STEAM_JSON_URL | [steam-games.json](https://raw.githubusercontent.com/vogler/free-games-claimer/main/steam-games.json) | A list of steam urls in json format to claim the games. |
| STEAM_GAMERPOWER | 1 | Claims steam games using [gamerpower api](https://www.gamerpower.com/api/giveaways?platform=steam&type=game). | | STEAM_GAMERPOWER | 0 | Claims steam games using [gamerpower api](https://www.gamerpower.com/api/giveaways?platform=steam&type=game). |
See `config.js` for all options. See `config.js` for all options.

View file

@ -51,7 +51,7 @@ export const cfg = {
steam_username: process.env.STEAM_USERNAME, steam_username: process.env.STEAM_USERNAME,
steam_password: process.env.STEAM_PASSWORD || process.env.PASSWORD, steam_password: process.env.STEAM_PASSWORD || process.env.PASSWORD,
steam_json: false || process.env.STEAM_JSON == '1', steam_json: process.env.STEAM_JSON == '1',
steam_json_url: process.env.STEAM_JSON_URL || 'https://raw.githubusercontent.com/vogler/free-games-claimer/main/steam-games.json', steam_json_url: process.env.STEAM_JSON_URL || 'https://raw.githubusercontent.com/vogler/free-games-claimer/main/steam-games.json',
steam_gamerpower: true || process.env.STEAM_GAMERPOWER == '1', steam_gamerpower: process.env.STEAM_GAMERPOWER == '1',
}; };

View file

@ -3,7 +3,6 @@ import { resolve, jsonDb, datetime, prompt, stealth, notify, html_game_list, han
import path from 'path'; import path from 'path';
import { existsSync, writeFileSync } from 'fs'; import { existsSync, writeFileSync } from 'fs';
import { cfg } from './config.js'; import { cfg } from './config.js';
import { config } from 'dotenv';
const screenshot = (...a) => resolve(cfg.dir.screenshots, 'steam', ...a); const screenshot = (...a) => resolve(cfg.dir.screenshots, 'steam', ...a);
@ -22,11 +21,10 @@ const context = await firefox.launchPersistentContext(cfg.dir.browser, {
// channel: 'chrome', // https://playwright.dev/docs/browsers#google-chrome--microsoft-edge // channel: 'chrome', // https://playwright.dev/docs/browsers#google-chrome--microsoft-edge
headless: false, headless: false,
viewport: { width: cfg.width, height: cfg.height }, viewport: { width: cfg.width, height: cfg.height },
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36', // see replace of Headless in util.newStealthContext. TODO Windows UA enough to avoid 'device not supported'? update if browser is updated? userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36',
// userAgent for firefox: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
locale: "en-US", // ignore OS locale to be sure to have english text for locators locale: "en-US", // ignore OS locale to be sure to have english text for locators
recordVideo: cfg.record ? { dir: 'data/record/', size: { width: cfg.width, height: cfg.height } } : undefined, // will record a .webm video for each page navigated; without size, video would be scaled down to fit 800x800 recordVideo: cfg.record ? { dir: 'data/record/', size: { width: cfg.width, height: cfg.height } } : undefined,
recordHar: cfg.record ? { path: `data/record/eg-${datetime()}.har` } : undefined, // will record a HAR file with network requests and responses; can be imported in Chrome devtools recordHar: cfg.record ? { path: `data/record/eg-${datetime()}.har` } : undefined,
args: [ // https://peter.sh/experiments/chromium-command-line-switches args: [ // https://peter.sh/experiments/chromium-command-line-switches
// don't want to see bubble 'Restore pages? Chrome didn't shut down correctly.' // don't want to see bubble 'Restore pages? Chrome didn't shut down correctly.'
// '--restore-last-session', // does not apply for crash/killed // '--restore-last-session', // does not apply for crash/killed
@ -47,16 +45,16 @@ const page = context.pages().length ? context.pages()[0] : await context.newPage
const notify_games = []; const notify_games = [];
let user; let user;
async function doLogin(){ async function doLogin() {
await page.goto(URL_LOGIN, { waitUntil: 'domcontentloaded' }); // default 'load' takes forever await page.goto(URL_LOGIN, { waitUntil: 'domcontentloaded' }); // default 'load' takes forever
if (cfg.steam_username && cfg.steam_password){ if (cfg.steam_username && cfg.steam_password) {
console.info('Using username and password from environment.'); console.info('Using username and password from environment.');
} }
else { else {
console.info('Press ESC to skip the prompts if you want to login in the browser (not possible in headless mode).'); console.info('Press ESC to skip the prompts if you want to login in the browser (not possible in headless mode).');
} }
const username = cfg.steam_username || await prompt({message: 'Enter username'}); const username = cfg.steam_username || await prompt({ message: 'Enter username' });
const password = username && (cfg.steam_password || await prompt({type: 'password', message: 'Enter password'})); const password = username && (cfg.steam_password || await prompt({ type: 'password', message: 'Enter password' }));
if (username && password) { if (username && password) {
await page.type('input[type=text]:visible', username); await page.type('input[type=text]:visible', username);
await page.type('input[type=password]:visible', password); await page.type('input[type=password]:visible', password);
@ -66,10 +64,8 @@ async function doLogin(){
} }
const auth = await page.getByText('You have a mobile authenticator protecting this account.').first(); const auth = await page.getByText('You have a mobile authenticator protecting this account.').first();
let isFirstCheck = true; let isFirstCheck = true;
while (await auth.isVisible()) while (await auth.isVisible()) {
{ if (isFirstCheck) {
if (isFirstCheck)
{
console.log("Steam requires confirmation from authenticator"); console.log("Steam requires confirmation from authenticator");
notify(`Steam requires confirmation from authenticator`); notify(`Steam requires confirmation from authenticator`);
isFirstCheck = false; isFirstCheck = false;
@ -78,9 +74,9 @@ async function doLogin(){
} }
} }
async function claim(){ async function claim() {
await page.goto(URL_CLAIM, { waitUntil: 'domcontentloaded' }); // default 'load' takes forever await page.goto(URL_CLAIM, { waitUntil: 'domcontentloaded' }); // default 'load' takes forever
await context.addCookies([{name: 'cookieSettings', value: '%7B%22version%22%3A1%2C%22preference_state%22%3A2%2C%22content_customization%22%3Anull%2C%22valve_analytics%22%3Anull%2C%22third_party_analytics%22%3Anull%2C%22third_party_content%22%3Anull%2C%22utm_enabled%22%3Atrue%7D', domain: 'store.steampowered.com', path: '/'}]); // Decline all cookies to get rid of banner to save space on screen. await context.addCookies([{ name: 'cookieSettings', value: '%7B%22version%22%3A1%2C%22preference_state%22%3A2%2C%22content_customization%22%3Anull%2C%22valve_analytics%22%3Anull%2C%22third_party_analytics%22%3Anull%2C%22third_party_content%22%3Anull%2C%22utm_enabled%22%3Atrue%7D', domain: 'store.steampowered.com', path: '/' }]); // Decline all cookies to get rid of banner to save space on screen.
const signIn = page.locator('a:has-text("Sign In")').first(); const signIn = page.locator('a:has-text("Sign In")').first();
while (await signIn.isVisible()) { while (await signIn.isVisible()) {
@ -101,18 +97,16 @@ async function claim(){
} }
} }
async function claimJson(){ async function claimJson() {
console.log("Claiming JSON"); console.log("Claiming JSON");
const response = await page.goto(cfg.steam_json_url); const response = await page.goto(cfg.steam_json_url);
const items = await response.json(); const items = await response.json();
for (const item of items) { for (const item of items) {
if (!await isClaimedUrl(item.url)){ if (!await isClaimedUrl(item.url)) {
console.log(item); console.log(item);
if (item.hasOwnProperty("startDate")) if (item.hasOwnProperty("startDate")) {
{
const date = Date.parse(item.startDate); const date = Date.parse(item.startDate);
if (date >= Date.now()) if (date >= Date.now()) {
{
console.log("game not available yet " + new Date(date)); console.log("game not available yet " + new Date(date));
return; return;
} }
@ -122,7 +116,7 @@ async function claimJson(){
} }
} }
async function claimGamerpower(){ async function claimGamerpower() {
console.log("Claiming Gamerpower"); console.log("Claiming Gamerpower");
const response = await page.goto("https://www.gamerpower.com/api/giveaways?platform=steam&type=game"); const response = await page.goto("https://www.gamerpower.com/api/giveaways?platform=steam&type=game");
const items = await response.json(); const items = await response.json();
@ -131,8 +125,8 @@ async function claimGamerpower(){
await page.goto(item.open_giveaway_url, { waitUntil: 'domcontentloaded' }); await page.goto(item.open_giveaway_url, { waitUntil: 'domcontentloaded' });
const url = page.url(); const url = page.url();
if (url.includes("https://store.steampowered.com/app")){ if (url.includes("https://store.steampowered.com/app")) {
if (!await isClaimedUrl(url)){ if (!await isClaimedUrl(url)) {
await claimGame(url); await claimGame(url);
} }
} }
@ -142,11 +136,11 @@ async function claimGamerpower(){
} }
} }
async function claimGame(url){ async function claimGame(url) {
await page.goto(url, { waitUntil: 'domcontentloaded'}); await page.goto(url, { waitUntil: 'domcontentloaded' });
const title = await page.locator('#appHubAppName').first().innerText(); const title = await page.locator('#appHubAppName').first().innerText();
const pattern = "/app/"; const pattern = "/app/";
let game_id = page.url().substring(page.url().indexOf(pattern)+pattern.length); let game_id = page.url().substring(page.url().indexOf(pattern) + pattern.length);
game_id = game_id.substring(0, game_id.indexOf("/")); game_id = game_id.substring(0, game_id.indexOf("/"));
db.data[user][game_id] ||= { title, time: datetime(), url: page.url() }; // this will be set on the initial run only! db.data[user][game_id] ||= { title, time: datetime(), url: page.url() }; // this will be set on the initial run only!
@ -154,13 +148,11 @@ async function claimGame(url){
notify_games.push(notify_game); // status is updated below notify_games.push(notify_game); // status is updated below
const alreadyOwned = await page.locator('.game_area_already_owned').first(); const alreadyOwned = await page.locator('.game_area_already_owned').first();
if (await alreadyOwned.isVisible()) if (await alreadyOwned.isVisible()) {
{
console.log("Game " + title + " already in library"); console.log("Game " + title + " already in library");
db.data[user][game_id].status ||= 'existed'; // does not overwrite claimed or failed db.data[user][game_id].status ||= 'existed'; // does not overwrite claimed or failed
} }
else else {
{
await page.locator(('#freeGameBtn')).click(); await page.locator(('#freeGameBtn')).click();
console.log("purchased"); console.log("purchased");
db.data[user][game_id].status = 'claimed'; db.data[user][game_id].status = 'claimed';
@ -174,9 +166,9 @@ async function claimGame(url){
async function isClaimedUrl(url) { async function isClaimedUrl(url) {
try { try {
const pattern = "/app/"; const pattern = "/app/";
let game_id = url.substring(url.indexOf(pattern)+pattern.length); let game_id = url.substring(url.indexOf(pattern) + pattern.length);
game_id = game_id.substring(0, game_id.indexOf("/")); game_id = game_id.substring(0, game_id.indexOf("/"));
var status = db.data[user][game_id]["status"]; const status = db.data[user][game_id]["status"];
return status === "existed" || status === "claimed"; return status === "existed" || status === "claimed";
} catch (error) { } catch (error) {
return false; return false;