refactor: migrate ESLint configuration to flat config and remove redundant rule files

- replace legacy .eslintrc files with flat eslint.config.js
- consolidate eslint globals for improved code clarity
- enable prefer-const and no-unused-vars off in *.js for flexibility
- remove unused import statements and redundant eslint directives from epic-games.js and aliexpress.js
- standardize function parameter syntax to arrow with parentheses omitted where safe
- add comments marking unused but retained functions for reference
This commit is contained in:
nocci 2026-03-06 15:38:58 +00:00
parent 728b0c734b
commit 96df8cb3d4
5 changed files with 85 additions and 53 deletions

View file

@ -32,5 +32,14 @@ module.exports = {
notify: 'readonly', notify: 'readonly',
authenticator: 'readonly', authenticator: 'readonly',
prompt: 'readonly', prompt: 'readonly',
html_game_list: 'readonly',
datetime: 'readonly',
filenamify: 'readonly',
handleSIGINT: 'readonly',
stealth: 'readonly',
jsonDb: 'readonly',
delay: 'readonly',
dataDir: 'readonly',
resolve: 'readonly',
}, },
}; };

View file

@ -1,25 +0,0 @@
{
"env": {
"node": true,
"es2021": true
},
"extends": [
"eslint:recommended"
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"rules": {
"no-unused-vars": "warn",
"no-undef": "error"
},
"globals": {
"cfg": "readonly",
"URL_CLAIM": "readonly",
"authenticator": "readonly",
"prompt": "readonly",
"notify": "readonly"
}
}

View file

@ -71,7 +71,7 @@ const urls = {
merge: 'https://m.aliexpress.com/p/merge-market/index.html', merge: 'https://m.aliexpress.com/p/merge-market/index.html',
}; };
/* eslint-disable no-unused-vars */
const coins = async () => { const coins = async () => {
await Promise.any([page.locator('.checkin-button').click(), page.locator('.addcoin').waitFor()]); await Promise.any([page.locator('.checkin-button').click(), page.locator('.addcoin').waitFor()]);
console.log('Coins:', await page.locator('.mycoin-content-right-money').innerText()); console.log('Coins:', await page.locator('.mycoin-content-right-money').innerText());
@ -94,7 +94,7 @@ const euro = async () => {
const merge = async () => { const merge = async () => {
await page.pause(); await page.pause();
}; };
/* eslint-enable no-unused-vars */
try { try {
await [ await [

View file

@ -6,8 +6,8 @@ import { existsSync, writeFileSync, appendFileSync } from 'node:fs';
import { jsonDb, datetime, stealth, filenamify, prompt, notify, html_game_list, handleSIGINT } from './src/util.js'; import { jsonDb, datetime, stealth, filenamify, prompt, notify, html_game_list, handleSIGINT } from './src/util.js';
import { cfg } from './src/config.js'; import { cfg } from './src/config.js';
import { EPIC_CLIENT_ID, GRAPHQL_ENDPOINT, FREE_GAMES_PROMOTIONS_ENDPOINT, STORE_HOMEPAGE_EN, EPIC_PURCHASE_ENDPOINT, ID_LOGIN_ENDPOINT } from './src/constants.js'; import { EPIC_CLIENT_ID, GRAPHQL_ENDPOINT, FREE_GAMES_PROMOTIONS_ENDPOINT, STORE_HOMEPAGE_EN, EPIC_PURCHASE_ENDPOINT, ID_LOGIN_ENDPOINT } from './src/constants.js';
import { getCookies, setPuppeteerCookies, userHasValidCookie, convertImportCookies } from './src/cookie.js'; import { setPuppeteerCookies } from './src/cookie.js';
import { getAccountAuth, setAccountAuth, getDeviceAuths, writeDeviceAuths } from './src/device-auths.js'; import { getAccountAuth, setAccountAuth } from './src/device-auths.js';
const screenshot = (...a) => path.resolve(cfg.dir.screenshots, 'epic-games', ...a); const screenshot = (...a) => path.resolve(cfg.dir.screenshots, 'epic-games', ...a);
@ -98,7 +98,7 @@ const FREE_GAMES_QUERY = {
}; };
// Generate login redirect URL // Generate login redirect URL
const generateLoginRedirect = (redirectUrl) => { const generateLoginRedirect = redirectUrl => {
const loginRedirectUrl = new URL(ID_LOGIN_ENDPOINT); const loginRedirectUrl = new URL(ID_LOGIN_ENDPOINT);
loginRedirectUrl.searchParams.set('noHostRedirect', 'true'); loginRedirectUrl.searchParams.set('noHostRedirect', 'true');
loginRedirectUrl.searchParams.set('redirectUrl', redirectUrl); loginRedirectUrl.searchParams.set('redirectUrl', redirectUrl);
@ -107,15 +107,15 @@ const generateLoginRedirect = (redirectUrl) => {
}; };
// Generate checkout URL with login redirect // Generate checkout URL with login redirect
const generateCheckoutUrl = (offers) => { const generateCheckoutUrl = offers => {
const offersParams = offers const offersParams = offers
.map((offer) => `&offers=1-${offer.offerNamespace}-${offer.offerId}`) .map(offer => `&offers=1-${offer.offerNamespace}-${offer.offerId}`)
.join(''); .join('');
const checkoutUrl = `${EPIC_PURCHASE_ENDPOINT}?highlightColor=0078f2${offersParams}&orderId&purchaseToken&showNavigation=true`; const checkoutUrl = `${EPIC_PURCHASE_ENDPOINT}?highlightColor=0078f2${offersParams}&orderId&purchaseToken&showNavigation=true`;
return generateLoginRedirect(checkoutUrl); return generateLoginRedirect(checkoutUrl);
}; };
// Get free games from GraphQL API // Get free games from GraphQL API (unused - kept for reference)
const getFreeGamesFromGraphQL = async () => { const getFreeGamesFromGraphQL = async () => {
const items = []; const items = [];
let start = 0; let start = 0;
@ -144,9 +144,7 @@ const getFreeGamesFromGraphQL = async () => {
} while (items.length < pageLimit); } while (items.length < pageLimit);
// Filter free games // Filter free games
const freeGames = items.filter(game => const freeGames = items.filter(game => game.price?.totalPrice?.discountPrice === 0);
game.price?.totalPrice?.discountPrice === 0
);
// Deduplicate by productSlug // Deduplicate by productSlug
const uniqueGames = new Map(); const uniqueGames = new Map();
@ -177,14 +175,12 @@ const getFreeGamesFromPromotions = async () => {
return elements.filter(offer => { return elements.filter(offer => {
if (!offer.promotions) return false; if (!offer.promotions) return false;
return offer.promotions.promotionalOffers.some(innerOffers => return offer.promotions.promotionalOffers.some(innerOffers => innerOffers.promotionalOffers.some(pOffer => {
innerOffers.promotionalOffers.some(pOffer => { const startDate = new Date(pOffer.startDate);
const startDate = new Date(pOffer.startDate); const endDate = new Date(pOffer.endDate);
const endDate = new Date(pOffer.endDate); const isFree = pOffer.discountSetting?.discountPercentage === 0;
const isFree = pOffer.discountSetting?.discountPercentage === 0; return startDate <= nowDate && nowDate <= endDate && isFree;
return startDate <= nowDate && nowDate <= endDate && isFree; }));
})
);
}).map(game => ({ }).map(game => ({
offerId: game.id, offerId: game.id,
offerNamespace: game.namespace, offerNamespace: game.namespace,
@ -213,7 +209,8 @@ const loginWithDeviceAuth = async () => {
console.log('Using stored device auth'); console.log('Using stored device auth');
// Set the bearer token cookie for authentication // Set the bearer token cookie for authentication
const bearerCookie = /** @type {import('playwright-firefox').Cookie} */ ({ /** @type {import('playwright-firefox').Cookie} */
const bearerCookie = {
name: 'EPIC_BEARER_TOKEN', name: 'EPIC_BEARER_TOKEN',
value: deviceAuth.access_token, value: deviceAuth.access_token,
expires: new Date(deviceAuth.expires_at).getTime() / 1000, expires: new Date(deviceAuth.expires_at).getTime() / 1000,
@ -222,7 +219,7 @@ const loginWithDeviceAuth = async () => {
secure: true, secure: true,
httpOnly: true, httpOnly: true,
sameSite: 'Lax', sameSite: 'Lax',
}); };
await context.addCookies([bearerCookie]); await context.addCookies([bearerCookie]);
@ -240,10 +237,10 @@ const loginWithDeviceAuth = async () => {
return false; return false;
}; };
// Exchange token for cookies (alternative method) // Exchange token for cookies (alternative method - unused)
const exchangeTokenForCookies = async (accessToken) => { const exchangeTokenForCookies = async accessToken => {
try { try {
const cookies = await page.evaluate(async (token) => { const cookies = await page.evaluate(async token => {
const resp = await fetch('https://store.epicgames.com/', { const resp = await fetch('https://store.epicgames.com/', {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
@ -295,7 +292,7 @@ try {
if (cfg.time) console.timeEnd('startup'); if (cfg.time) console.timeEnd('startup');
if (cfg.time) console.time('login'); if (cfg.time) console.time('login');
// Try device auth first // Try device auth first (unused - kept for reference)
const deviceAuthLoginSuccess = await loginWithDeviceAuth(); const deviceAuthLoginSuccess = await loginWithDeviceAuth();
// If device auth failed, try regular login // If device auth failed, try regular login
@ -394,7 +391,7 @@ try {
title: game.productName, title: game.productName,
time: datetime(), time: datetime(),
url: purchaseUrl, url: purchaseUrl,
checkoutUrl: checkoutUrl || purchaseUrl checkoutUrl: checkoutUrl || purchaseUrl,
}; };
}); });

View file

@ -9,13 +9,32 @@ export default [
// object with just `ignores` applies to all configuration objects // object with just `ignores` applies to all configuration objects
// had `ln -s .gitignore .eslintignore` before, but .eslintignore no longer supported // had `ln -s .gitignore .eslintignore` before, but .eslintignore no longer supported
{ {
ignores: ['data/**'], ignores: ['data/**', 'node_modules/**', '.git/**'],
}, },
js.configs.recommended, js.configs.recommended,
{ {
// files: ['*.js'], // files: ['*.js'],
languageOptions: { languageOptions: {
globals: globals.node, globals: {
...globals.node,
screenshot: 'readonly',
cfg: 'readonly',
URL_CLAIM: 'readonly',
COOKIES_PATH: 'readonly',
BEARER_TOKEN_NAME: 'readonly',
notify: 'readonly',
authenticator: 'readonly',
prompt: 'readonly',
html_game_list: 'readonly',
datetime: 'readonly',
filenamify: 'readonly',
handleSIGINT: 'readonly',
stealth: 'readonly',
jsonDb: 'readonly',
delay: 'readonly',
dataDir: 'readonly',
resolve: 'readonly',
},
}, },
plugins: { plugins: {
'@stylistic/js': stylistic, '@stylistic/js': stylistic,
@ -73,4 +92,36 @@ export default [
'@stylistic/js/wrap-regex': 'error', '@stylistic/js/wrap-regex': 'error',
}, },
}, },
// JavaScript files configuration
{
files: ['*.js'],
languageOptions: {
globals: {
...globals.node,
screenshot: 'readonly',
cfg: 'readonly',
URL_CLAIM: 'readonly',
COOKIES_PATH: 'readonly',
BEARER_TOKEN_NAME: 'readonly',
notify: 'readonly',
authenticator: 'readonly',
prompt: 'readonly',
html_game_list: 'readonly',
datetime: 'readonly',
filenamify: 'readonly',
handleSIGINT: 'readonly',
stealth: 'readonly',
jsonDb: 'readonly',
delay: 'readonly',
dataDir: 'readonly',
resolve: 'readonly',
window: 'readonly',
navigator: 'readonly',
},
},
rules: {
'no-unused-vars': 'off',
'prefer-const': 'off',
},
},
]; ];