@matveymirman/iracing-node-api
Version:
A nodejs wrapper for Iracing's data api.
180 lines (179 loc) • 6.54 kB
JavaScript
import Axios from 'axios';
import { wrapper } from 'axios-cookiejar-support';
import { SHA256, enc } from 'crypto-js';
import StatusCodes from 'http-status-codes';
import { CookieJar } from 'tough-cookie';
import UserAgent from 'user-agents';
class IracingClient {
authenticated;
apiClient;
email;
password;
interval;
options;
agent;
constructor(email, password, options = { shouldUseInterval: true }) {
if (!email || !password) {
throw new Error(`Iracing Api: Unable to initialze client. Missing email or password`);
}
this.email = email;
this.password = password;
this.options = options;
this.authenticated = false;
this.agent = new UserAgent({ platform: 'Win32' });
this.apiClient = wrapper(Axios.create({
jar: new CookieJar(),
withCredentials: true,
baseURL: 'https://members-ng.iracing.com',
headers: {
'User-Agent': this.agent.toString()
}
}));
this.signIn();
this.interval = null;
this.handleError();
}
handleError() {
this.apiClient.interceptors.response.use(async (config) => {
if (config.status === StatusCodes.UNAUTHORIZED ||
config.status === StatusCodes.FORBIDDEN) {
this.authenticated = false;
this.signIn();
}
return config;
}, (error) => {
if (error.status === StatusCodes.UNAUTHORIZED ||
error.status === StatusCodes.FORBIDDEN) {
this.authenticated = false;
this.signIn();
}
});
}
encodeCredentials(email, password) {
const hash = SHA256(password + email.toLowerCase());
return enc.Base64.stringify(hash);
}
async signIn() {
const hash = this.encodeCredentials(this.email, this.password);
try {
const res = await this.apiClient.post('/auth', {
email: this.email,
password: hash
});
if (res?.data?.authcode) {
this.authenticated = true;
}
}
catch (error) {
throw error;
}
}
async getResource(resourceLink = '') {
if (!resourceLink) {
throw new Error('Missing resource url');
}
try {
const res = await this.apiClient.get(resourceLink);
return res.data;
}
catch (error) {
throw error;
}
}
async getCarAssets() {
try {
await this.signIn();
const res = await this.apiClient.get('/data/car/assets');
const assets = await this.getResource(res.data?.link);
return assets;
}
catch (error) {
throw error;
}
}
async getTrackData() {
await this.signIn();
const res = await this.apiClient.get('/data/track/get');
const trackData = await this.getResource(res.data?.link);
return trackData;
}
async getTrackAssets() {
await this.signIn();
const res = await this.apiClient.get('/data/track/assets');
const data = await this.getResource(res.data?.link);
return data;
}
async getCarData() {
await this.signIn();
const res = await this.apiClient.get('/data/car/get');
const carData = await this.getResource(res.data?.link);
return carData;
}
async getSessionResults(subsessionId) {
await this.signIn();
const res = await this.apiClient.get(`/data/results/get?subsession_id=${subsessionId}`);
const results = await this.getResource(res.data?.link);
return results;
}
async getSessionLogs(subsessionId, sessionNumber) {
await this.signIn();
const res = await this.apiClient.get(`/data/results/event_log?subsession_id=${subsessionId}&simsession_number=${sessionNumber}`);
const logs = await this.getResource(res.data?.link);
return logs;
}
async getLapChartData(subsessionId, sessionNumber) {
await this.signIn();
const res = await this.apiClient.get(`/data/results/lap_chart_data?subsession_id=${subsessionId}&simsession_number=${sessionNumber}`);
const signedData = await this.getResource(res.data?.link);
return signedData;
}
async getMemberStatsHistory(category, chart_type, memberId) {
await this.signIn();
const types = {
iRating: 1,
'tt-rating': 2,
sr: 3
};
const categories = {
oval: 1,
road: 2,
'dirt-oval': 3,
dirt: 4
};
const res = await this.apiClient.get(`/data/member/chart_data?category_id=${categories[category]}&chart_type=${types[chart_type]}&cust_id=${memberId}`);
const signedResponse = await this.getResource(res.data?.link);
return signedResponse;
}
async getMember(memberId) {
await this.signIn();
const res = await this.apiClient.get(`data/member/get?cust_ids=${memberId}`);
const signedResponse = await this.getResource(res.data?.link);
return (signedResponse.members.find((member) => member.cust_id === memberId) ??
null);
}
async getLeague(leagueId) {
await this.signIn();
const res = await this.apiClient.get(`data/league/get?league_id=${leagueId}`);
const signedData = await this.getResource(res.data?.link);
return signedData;
}
async getLeagueSeasons(leagueId, getRetired) {
await this.signIn();
const res = await this.apiClient.get(`data/league/seasons?league_id=${leagueId}&retired=${getRetired || false}`);
const signedData = await this.getResource(res.data?.link);
return signedData;
}
async getLeagueRoster(leagueId) {
await this.signIn();
const res = await this.apiClient.get(`data/league/roster?league_id=${leagueId}`);
const signedData = await this.getResource(res.data?.data_url);
return signedData;
}
async getLeagueSeasonSesssions(leagueId, seasonId) {
await this.signIn();
const res = await this.apiClient.get(`data/league/season_sessions?league_id=${leagueId}&season_id=${seasonId}`);
const signedData = await this.getResource(res.data?.link);
return signedData;
}
}
export default IracingClient;