free-games-claimer/src/logger.js
root 393f70d409
All checks were successful
build-and-push / lint (push) Successful in 9s
build-and-push / sonar (push) Successful in 21s
build-and-push / docker (push) Successful in 13s
feat: Add OAuth Device Flow login to bypass Cloudflare
- src/device-login.js: New module implementing Epic Games OAuth Device Flow
- src/logger.js: Simple logger module for consistent logging
- src/config.js: Add deviceAuthClientId and deviceAuthSecret config
- epic-claimer-new.js: Use OAuth Device Flow instead of browser login
- Cloudflare bypass: Device Flow uses API, user logs in own browser
- Based on: https://github.com/claabs/epicgames-freegames-node

How it works:
1. Get client credentials from Epic OAuth API
2. Get device authorization code with verification URL
3. Send user notification with login link
4. User clicks link and logs in (handles Cloudflare manually)
5. Poll for authorization completion
6. Save and use access/refresh tokens
7. Tokens auto-refresh on expiry

Benefits:
- No Cloudflare issues (no bot detection)
- Persistent tokens (no repeated logins)
- Works in headless mode
- More reliable than browser automation
2026-03-08 14:26:44 +00:00

64 lines
2.2 KiB
JavaScript

/**
* Simple logger for free-games-claimer
*/
const LOG_LEVELS = {
trace: 0,
debug: 1,
info: 2,
warn: 3,
error: 4,
};
const currentLevel = process.env.LOG_LEVEL
? LOG_LEVELS[process.env.LOG_LEVEL.toLowerCase()]
: LOG_LEVELS.info;
function formatMessage(level, module, message, data) {
const timestamp = new Date().toISOString();
const moduleStr = module ? `[${module}] ` : '';
const dataStr = data && Object.keys(data).length > 0 ? ' ' + JSON.stringify(data) : '';
return `${timestamp} ${level.toUpperCase().padEnd(5)} ${moduleStr}${message}${dataStr}`;
}
function createLogger(module) {
return {
trace: (dataOrMessage, message) => {
if (currentLevel <= LOG_LEVELS.trace) {
const [data, msg] = typeof dataOrMessage === 'string' ? [null, dataOrMessage] : [dataOrMessage, message];
console.log(formatMessage('trace', module, msg || '', data));
}
},
debug: (dataOrMessage, message) => {
if (currentLevel <= LOG_LEVELS.debug) {
const [data, msg] = typeof dataOrMessage === 'string' ? [null, dataOrMessage] : [dataOrMessage, message];
console.log(formatMessage('debug', module, msg || '', data));
}
},
info: (dataOrMessage, message) => {
if (currentLevel <= LOG_LEVELS.info) {
const [data, msg] = typeof dataOrMessage === 'string' ? [null, dataOrMessage] : [dataOrMessage, message];
console.log(formatMessage('info', module, msg || '', data));
}
},
warn: (dataOrMessage, message) => {
if (currentLevel <= LOG_LEVELS.warn) {
const [data, msg] = typeof dataOrMessage === 'string' ? [null, dataOrMessage] : [dataOrMessage, message];
console.log(formatMessage('warn', module, msg || '', data));
}
},
error: (dataOrMessage, message) => {
if (currentLevel <= LOG_LEVELS.error) {
const [data, msg] = typeof dataOrMessage === 'string' ? [null, dataOrMessage] : [dataOrMessage, message];
console.log(formatMessage('error', module, msg || '', data));
}
},
child: childData => {
const childModule = childData?.module || module;
return createLogger(childModule);
},
};
}
const logger = createLogger('root');
export default logger;