const fetch = require('node-fetch'); const Vehicle = require('../models/vehicle'); const Utils = require('../utils'); const baseUrl = 'https://vin01.ru/v2'; const reportBaseUrl = `${baseUrl}/gibddApp.php`; class Vin01Provider { static async getVin(number, token) { let url = `${baseUrl}/getVin.php?key=${token}&gosNumber=${encodeURIComponent(number)}`; let result = await fetch(url); let json = await result.json(); if(json.success && json.code == 200) { return json.data.vin; } else { throw Error('Vin01 provider failed to get VIN'); } } static async runCheck(type, vin, token) { let result = await fetch(reportBaseUrl, { method: 'POST', body: new URLSearchParams({ typeCheckValue: type, vinValue: vin, key: token, token: null }) }); return await result.json(); } static checkErrors(result) { if(result.status == 'fulfilled') { let json = result.value; if(json.status == 200) { if('status' in json.data) { if(json.data.status == 200) { result.value = json.data; return result; } else { return { status: 'rejected', reason: `[${json.data.status}] ${json.data.message}` }; } } else { result.value = json.data; return result; } } else { return { status: 'rejected', reason: `[${json.status}] ${json.code}` }; } } else { return result; } } static async getReport(number, token) { try { let vin = await Vin01Provider.getVin(number, token); console.log('vin01 found VIN: ', vin); let checks = [Vin01Provider.runCheck('base', vin, token), Vin01Provider.runCheck('history', vin, token)]; let [base, history] = (await Promise.allSettled(checks)).map(Vin01Provider.checkErrors); if(base.status == 'rejected' && history.status == 'rejected') { console.log('Vin01 base error: ', base.reason); console.log('Vin01 history error: ', history.reason); let vehicle = new Vehicle(); vehicle.vin1 = Utils.cyrillicToLatin(vin); vehicle.debugInfo = { vin01vin: { fields: 0n, error: null }, vin01history: { fields: 0n, error: history.reason }, vin01base: { fields: 0n, error: base.reason } } return vehicle; } else if(base.status == 'rejected') { console.log('vin01 found history'); let vehicle = Vehicle.fromVin01History(history.value); vehicle.number = number; Object.assign(vehicle.debugInfo, { vin01vin: { fields: 0n, error: null }, vin01base: { fields: 0n, error: base.reason } }); return vehicle; } else if(history.status == 'rejected') { console.log('vin01 found base info'); let vehicle = Vehicle.fromVin01Base(base.value); vehicle.number = number; Object.assign(vehicle.debugInfo, { vin01vin: { fields: 0n, error: null }, vin01history: { fields: 0n, error: history.reason } }); return vehicle; } else { // Both history and base reports were successfully received, merge them in one report let baseVehicle = Vehicle.fromVin01Base(base.value); let historyVehicle = Vehicle.fromVin01History(history.value); historyVehicle.brand.name.normalized = baseVehicle.brand.name.normalized; historyVehicle.model = baseVehicle.model; for(let period of historyVehicle.ownershipPeriods) { let basePeriod = baseVehicle.ownershipPeriods.find(p => p.from == period.from); if(basePeriod) { period.region = basePeriod.region; period.registrationRegion = basePeriod.registrationRegion; period.locality = basePeriod.locality; if(basePeriod.street) { period.street = basePeriod.street; } if(basePeriod.building) { period.building = basePeriod.building; } if(basePeriod.inn) { period.inn = basePeriod.inn; } if(basePeriod.code) { period.code = basePeriod.code; } } } Object.assign(historyVehicle.debugInfo, { vin01vin: { fields: 0n, error: null } }); Object.assign(historyVehicle.debugInfo, baseVehicle.debugInfo); historyVehicle.number = number; return historyVehicle; } } catch(ex) { ex.debugInfo = { vin01vin: { fields: 0n, error: ex.message }, vin01history: { fields: 0n, error: 'Not applicable' }, vin01base: { fields: 0n, error: 'Not applicable' } } throw ex; } } } module.exports = Vin01Provider;