UNPKG

domrobot-client

Version:
175 lines (147 loc) 5.44 kB
import * as otplib from 'otplib'; export class ApiClient { public static readonly CLIENT_VERSION = '3.0.2'; public static readonly API_URL_LIVE = 'https://api.domrobot.com/jsonrpc/'; public static readonly API_URL_OTE = 'https://api.ote.domrobot.com/jsonrpc/'; public static generateClientTransactionId(): string { return 'DomRobot-' + Math.round(Math.random() * 1000000000); } private readonly apiUrl: string; private language: string; private debugMode: boolean; private cookie: string; private headers: Record<string, any>; /** * @param apiUrl url of the API. * @param language default language for future API requests. * @param debugMode whether requests and responses should be printed out. * @param headers Optional HTTP headers to be included in all API requests. */ constructor( apiUrl: string = ApiClient.API_URL_OTE, language: string = Language.EN, debugMode: boolean = false, headers: Record<string, any> = {}, ) { this.apiUrl = apiUrl; this.language = language; this.debugMode = debugMode; this.cookie = null; this.headers = headers; } /** * Makes an API call. * * @param apiMethod The name of the method called in the API. * @param methodParams An object of parameters added to the request. * @param clientTransactionId Id sent with every request to distinguish your api requests in case you need support. * @param language Language for the API request. Default is value of field language. * @param cacheOption HTTP cache options * @param nextjsOptions Next.js options */ public async callApi( apiMethod: string, methodParams: any = {}, clientTransactionId: string = ApiClient.generateClientTransactionId(), language: string = this.language, cacheOption?: 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached' | 'default', nextjsOptions?: object, ): Promise<any> { if ('clTRID'! in methodParams && clientTransactionId !== null) { methodParams.clTRID = clientTransactionId; } if ('lang'! in methodParams) { methodParams.lang = language; } const requestBody = JSON.stringify({ method: apiMethod, params: methodParams, }); let fetchOption = { method: 'POST', headers: new Headers({ 'Content-Type': 'application/json', Cookie: this.cookie, 'User-Agent': `DomRobot/${ApiClient.CLIENT_VERSION} (Node ${process.version})`, ...(this.headers ?? {}), }), body: requestBody, cache: cacheOption ?? 'default', }; if (nextjsOptions !== undefined) { fetchOption = { ...fetchOption, ...nextjsOptions }; } const response = await fetch(this.apiUrl, fetchOption); if (apiMethod === 'account.login') { this.cookie = response.headers.get('set-cookie'); } const data = await response.json(); if (this.debugMode) { console.info(`Request (${apiMethod}): ${requestBody}`); console.info(`Response (${apiMethod}): ${JSON.stringify(data)}`); } return data; } /** * Performs a login at the API and saves the session for following API calls. * * @param username your username. * @param password your password. * @param sharedSecret */ public async login(username: string, password: string, sharedSecret: string = null): Promise<any> { const loginResult = await this.callApi('account.login', { user: username, pass: password }); if (loginResult.code === 1000 && 'tfa' in loginResult.resData && loginResult.resData.tfa !== '0') { if (sharedSecret === null) { return Promise.reject('API requests two factor challenge but no shared secret is given. Aborting.'); } const secretCode = otplib.authenticator.generate(sharedSecret); const unlockResult = await this.callApi('account.unlock', { tan: secretCode }); if (unlockResult.code !== 1000) { return unlockResult; } } return loginResult; } /** * Performs a logout at the API and destroys the current session. */ public async logout(): Promise<any> { return await this.callApi('account.logout').then(() => (this.cookie = null)); } public getApiUrl(): string { return this.apiUrl; } public getLanguage(): string { return this.language; } public setLanguage(value: string) { this.language = value; } public isDebugMode(): boolean { return this.debugMode; } public setDebugMode(value: boolean) { this.debugMode = value; } public getCookie(): string { return this.cookie; } public setCookie(cookie: string) { this.cookie = cookie; } public setHeaders(headers: Record<string, any>) { this.headers = headers; } public getHeaders(): Record<string, any> { return this.headers; } } /** * The API response-message language. */ export enum Language { EN = 'en', DE = 'de', ES = 'es', }