UNPKG

bluelinky2

Version:

An unofficial nodejs API wrapper for Hyundai bluelink

127 lines (114 loc) 5.15 kB
import { Brand } from '../interfaces/common.interfaces'; import { readFile } from 'fs'; import { promisify } from 'util'; import got from 'got'; export type EULanguages = 'cs'|'da'|'nl'|'en'|'fi'|'fr'|'de'|'it'|'pl'|'hu'|'no'|'sk'|'es'|'sv'; export const EU_LANGUAGES: EULanguages[] = ['cs', 'da', 'nl', 'en', 'fi', 'fr', 'de', 'it', 'pl', 'hu', 'no', 'sk', 'es', 'sv']; export const DEFAULT_LANGUAGE: EULanguages = 'en'; interface StampCollection { stamps: string[]; generated: string; frequency: number; } export interface EuropeanBrandEnvironment { brand: Brand; host: string; baseUrl: string; clientId: string; appId: string; endpoints: { integration: string; silentSignIn: string; session: string; login: string; language: string; redirectUri: string; token: string; }, basicToken: string; GCMSenderID: string; stamp: (stampsFile?: string) => Promise<string>; brandAuthUrl: (options: { language: EULanguages; serviceId: string; userId: string; }) => string; } const cachedStamps = new Map<string, StampCollection>(); const getAndCacheStamps = async (file: string, stampsFile = `https://raw.githubusercontent.com/neoPix/bluelinky-stamps/master/${file}.v2.json`): Promise<StampCollection> => { if (stampsFile.startsWith(('file://'))) { const [,path] = stampsFile.split('file://'); const content = await promisify(readFile)(path); return JSON.parse(content.toString('utf-8')); } const { body } = await got(stampsFile, { json: true }); cachedStamps.set(file, body as StampCollection); return body as StampCollection; }; const getStamp = (stampFileKey: string) => async (stampsFile?: string) => { const { stamps, generated, frequency } = cachedStamps.get(stampFileKey) ?? await getAndCacheStamps(stampFileKey, stampsFile); const generatedDate = new Date(generated); const millisecondsSinceStampsGeneration = Date.now() - generatedDate.getTime(); const position = Math.floor(millisecondsSinceStampsGeneration / frequency); if (position / (stamps.length - 1) >= .9) { cachedStamps.delete(stampFileKey); } return stamps[Math.min(position, stamps.length - 1)]; }; const getEndpoints = (baseUrl: string, clientId: string): EuropeanBrandEnvironment['endpoints'] => ({ session: `${baseUrl}/api/v1/user/oauth2/authorize?response_type=code&state=test&client_id=${clientId}&redirect_uri=${baseUrl}/api/v1/user/oauth2/redirect`, login: `${baseUrl}/api/v1/user/signin`, language: `${baseUrl}/api/v1/user/language`, redirectUri: `${baseUrl}/api/v1/user/oauth2/redirect`, token: `${baseUrl}/api/v1/user/oauth2/token`, integration: `${baseUrl}/api/v1/user/integrationinfo`, silentSignIn: `${baseUrl}/api/v1/user/silentsignin`, }); const getHyundaiEnvironment = (): EuropeanBrandEnvironment => { const host = 'prd.eu-ccapi.hyundai.com:8080'; const baseUrl = `https://${host}`; const clientId = '6d477c38-3ca4-4cf3-9557-2a1929a94654'; const appId = '014d2225-8495-4735-812d-2616334fd15d'; return { brand: 'hyundai', host, baseUrl, clientId, appId, endpoints: Object.freeze(getEndpoints(baseUrl, clientId)), basicToken: 'Basic NmQ0NzdjMzgtM2NhNC00Y2YzLTk1NTctMmExOTI5YTk0NjU0OktVeTQ5WHhQekxwTHVvSzB4aEJDNzdXNlZYaG10UVI5aVFobUlGampvWTRJcHhzVg==', GCMSenderID: '414998006775', stamp: getStamp(`hyundai-${appId}`), brandAuthUrl({ language, serviceId, userId }) { const newAuthClientId = '64621b96-0f0d-11ec-82a8-0242ac130003'; return `https://eu-account.hyundai.com/auth/realms/euhyundaiidm/protocol/openid-connect/auth?client_id=${newAuthClientId}&scope=openid%20profile%20email%20phone&response_type=code&hkid_session_reset=true&redirect_uri=${baseUrl}/api/v1/user/integration/redirect/login&ui_locales=${language}&state=${serviceId}:${userId}`; } }; }; const getKiaEnvironment = (): EuropeanBrandEnvironment => { const host = 'prd.eu-ccapi.kia.com:8080'; const baseUrl = `https://${host}`; const clientId = 'fdc85c00-0a2f-4c64-bcb4-2cfb1500730a'; const appId = 'e7bcd186-a5fd-410d-92cb-6876a42288bd'; return { brand: 'kia', host, baseUrl, clientId, appId, endpoints: Object.freeze(getEndpoints(baseUrl, clientId)), basicToken: 'Basic ZmRjODVjMDAtMGEyZi00YzY0LWJjYjQtMmNmYjE1MDA3MzBhOnNlY3JldA==', GCMSenderID: '345127537656', stamp: getStamp(`kia-${appId}`), brandAuthUrl({ language, serviceId, userId }) { const newAuthClientId = '572e0304-5f8d-4b4c-9dd5-41aa84eed160'; return `https://eu-account.kia.com/auth/realms/eukiaidm/protocol/openid-connect/auth?client_id=${newAuthClientId}&scope=openid%20profile%20email%20phone&response_type=code&hkid_session_reset=true&redirect_uri=${baseUrl}/api/v1/user/integration/redirect/login&ui_locales=${language}&state=${serviceId}:${userId}`; } }; }; export const getBrandEnvironment = (brand: Brand): EuropeanBrandEnvironment => { switch (brand) { case 'hyundai': return Object.freeze(getHyundaiEnvironment()); case 'kia': return Object.freeze(getKiaEnvironment()); default: throw new Error(`Constructor ${brand} is not managed.`); } };