Files
ultimate-ban-tracker/frontend/electron/services/scraper.ts

78 lines
2.8 KiB
TypeScript

import axios from 'axios';
import * as cheerio from 'cheerio';
export interface CooldownData {
isActive: boolean;
expiresAt?: Date;
}
// Custom error to identify session death
export class SteamAuthError extends Error {
constructor(message: string) {
super(message);
this.name = "SteamAuthError";
}
}
export const scrapeCooldown = async (steamId: string, steamLoginSecure: string): Promise<CooldownData> => {
const url = `https://steamcommunity.com/profiles/${steamId}/gcpd/730?tab=matchmaking`;
try {
const response = await axios.get(url, {
headers: {
'Cookie': steamLoginSecure,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
},
timeout: 10000,
validateStatus: (status) => status < 500 // Allow redirects to handle them manually
});
// If Steam redirects us to the login page, the cookie is dead
if (response.data.includes('Sign In') || response.request.path.includes('/login')) {
throw new SteamAuthError('Invalid or expired steamLoginSecure cookie');
}
const $ = cheerio.load(response.data);
if (!response.data.includes('Personal Game Data')) {
throw new SteamAuthError('Session invalid: Personal Game Data not accessible');
}
let expirationDate: Date | undefined = undefined;
$('table').each((_, table) => {
const headers = $(table).find('th').map((_, th) => $(th).text().trim()).get();
const expirationIndex = headers.findIndex(h => h.includes('Competitive Cooldown Expiration') || h.includes('Cooldown Expiration'));
if (expirationIndex !== -1) {
const rows = $(table).find('tr').not(':has(th)');
rows.each((_, row) => {
const dateText = $(row).find('td').eq(expirationIndex).text().trim();
if (dateText && dateText !== '') {
const cleanDateText = dateText.replace(' GMT', ' UTC');
const parsed = new Date(cleanDateText);
if (!isNaN(parsed.getTime())) {
if (!expirationDate || parsed > (expirationDate as Date)) expirationDate = parsed;
}
}
});
}
});
if (expirationDate && (expirationDate as Date).getTime() > Date.now()) {
return { isActive: true, expiresAt: expirationDate };
}
const content = $('#personal_game_data_content').text();
if (content.includes('Competitive Cooldown') || content.includes('Your account is currently')) {
return { isActive: true };
}
return { isActive: false };
} catch (error: any) {
if (error instanceof SteamAuthError) throw error;
console.error(`[Scraper] Network/Internal Error for ${steamId}:`, error.message);
throw error; // Generic errors don't trigger re-auth
}
};