AutoCatBackend/data_providers/vin01.js

161 lines
4.8 KiB
JavaScript

const fetch = require('node-fetch');
const AbortController = require('abort-controller');
const DebugInfo = require('../models/DebugInfo');
const Vehicle = require('../models/vehicle');
const Utils = require('../utils/utils');
const baseUrl = 'https://vin01.ru/v2';
const reportBaseUrl = `${baseUrl}/gibddApp.php`;
async function fetchWithTimeout(url, params, timeout) {
const controller = new AbortController();
const timeoutId = setTimeout(() => {
controller.abort();
}, timeout);
let requestParams = params ?? {};
requestParams.signal = controller.signal;
try {
return await fetch(url, requestParams);
} finally {
clearInterval(timeoutId);
}
}
class Vin01Provider {
static async getVin(number, token) {
let url = `${baseUrl}/getVin.php?key=${token}&gosNumber=${encodeURIComponent(number)}`;
let result = await fetchWithTimeout(url, null, 14000);
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 fetchWithTimeout(reportBaseUrl, {
method: 'POST',
body: new URLSearchParams({
typeCheckValue: type,
vinValue: vin,
key: token,
token: null
})
}, 25000);
console.log('Vin01 response for: ', type);
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: Error(`[${json.data.status}] ${json.data.message}`) };
}
} else {
result.value = json.data;
return result;
}
} else {
return { status: 'rejected', reason: Error(`[${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.message);
console.log('Vin01 history error: ', history.reason.message);
let vehicle = new Vehicle();
vehicle.vin1 = Utils.cyrillicToLatin(vin);
vehicle.debugInfo = {
vin01vin: new DebugInfo(),
vin01history: DebugInfo.fromError(history.reason.message),
vin01base: DebugInfo.fromError(base.reason.message)
};
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: new DebugInfo(),
vin01base: DebugInfo.fromError(base.reason.message)
});
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: new DebugInfo(),
vin01history: DebugInfo.fromError(history.reason.message)
});
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: new DebugInfo() });
Object.assign(historyVehicle.debugInfo, baseVehicle.debugInfo);
historyVehicle.number = number;
return historyVehicle;
}
} catch(ex) {
ex.debugInfo = {
vin01vin: DebugInfo.fromError(ex.message),
vin01history: DebugInfo.fromError('Not applicable (VIN was not found)'),
vin01base: DebugInfo.fromError('Not applicable (VIN was not found)')
};
throw ex;
}
}
}
module.exports = Vin01Provider;