Implement scaffolding for Tauron API utility class

This commit is contained in:
2024-11-12 15:42:24 +01:00
parent ada51916f5
commit da873dc054
2 changed files with 121 additions and 0 deletions

106
src/tauron/index.ts Normal file
View File

@@ -0,0 +1,106 @@
import axios, { Axios, AxiosResponse } from "axios";
import { wrapper } from 'axios-cookiejar-support';
import { CookieJar, MemoryCookieStore } from 'tough-cookie';
import { FileCookieStore } from 'tough-cookie-file-store';
import { EnergyDTO, Payload } from "./types";
export * from './types';
const LOGIN_API = `https://logowanie.tauron-dystrybucja.pl/login`;
const BASE_URL = 'https://elicznik.tauron-dystrybucja.pl';
/**
* Utility class for Tauron API.
* @param username - file containing a username of Tauron account
* @param password - file containing a password of Tauron account
* @param point - the measure point name - should be retrieved with browser dev-tools on website
* @param cookiePath - the path to the json file with cookie jar
*/
export const Tauron = class {
#http: Axios;
#username: string;
#password: string;
#point: string;
constructor(username: string, password: string, point: string, cookiePath = "./cookies.json") {
// TODO: It should be paths instead of raw credentials
this.#username = username;
this.#password = password;
this.#point = point;
this.#http = wrapper(axios.create({
baseURL: BASE_URL,
jar: new CookieJar(new FileCookieStore(cookiePath)),
headers: {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/jxl,image/webp,image/png,image/svg+xml,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate, br, zstd',
'Sec-GPC': '1',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Priority': 'u=0, i',
},
}));
}
/**
* Performs the whole login process flow including:
* - directing to the main page
* - doing toe actual login
* - setting the measurement base point
*/
async #login() {
await this.#http.get(LOGIN_API);
await this.#http.postForm(LOGIN_API, {
username: this.#username,
password: this.#password,
service: BASE_URL
});
await this.#http.postForm('/ustaw_punkt', {
"site[client]": this.#point,
"page": "energy"
});
}
/**
* Generic function which performs the HTTP request.
* If the request fails, the login attempt will be performed and the function will be invoked again
* with new session cookies.
* @param callback function which performs the request on Axios instance being passed as argument
* @returns response from callback function
*/
async query<T>(callback: (http: Axios) => Promise<AxiosResponse<T>>): Promise<AxiosResponse<T>> {
try {
return await callback(this.#http);
} catch(e) {
console.log("Session expired, login requested");
await this.#login();
return await callback(this.#http);
}
}
/**
* Returns the energy data per specific day.
* @param day measurement day
* @returns the energy data from Tauron API
*/
async getEnergyForDay(day: string): Promise<EnergyDTO> {
const response = await this.query(h => h.postForm<Payload<EnergyDTO>>('/energia/api', {
from: day,
to: day,
type: "consum",
profile: "full time"
}));
if (!response.data.success) {
throw new Error(`Invalid energy data request: ${JSON.stringify(response.data)}`);
}
return response.data.data;
}
};

15
src/tauron/types.ts Normal file
View File

@@ -0,0 +1,15 @@
export type Payload<T> = {
success: boolean;
data: T;
}
export type EnergyDTO = {
values: number[];
zones: Record<string, number>;
sum: number;
chartZones: Record<string, boolean[]>;
labels: number[];
tooltipLabels: string[];
zonesName: Record<string, string>;
tariff: string;
}