Adding photos from ads to general photos section

This commit is contained in:
Selim Mustafaev 2024-08-15 19:34:02 +03:00
parent 932cdfe8e9
commit 105bd25dc2
2 changed files with 213 additions and 175 deletions

View File

@ -1,55 +1,52 @@
import { createHash } from 'crypto'; import { createHash } from "crypto";
import Utils from '../utils/utils.js'; import Utils from "../utils/utils.js";
import DebugInfo from '../models/DebugInfo.js'; import DebugInfo from "../models/DebugInfo.js";
const baseUrl = 'https://www.nomerogram.ru/api/v1.1'; const baseUrl = "https://www.nomerogram.ru/api/v1.1";
const secretSuffix = 'queivoo1ieNgae2e'; const secretSuffix = "queivoo1ieNgae2e";
const appId = 'p15'; const appId = "p15";
const deviceId = '01b854631cb28e175ffbcccf6114acc3'; const deviceId = "01b854631cb28e175ffbcccf6114acc3";
const from = 'search'; const from = "search";
const userAgent = 'Nomerogram/2.18 (iPhone; iOS 13.7; Scale/2.00)'; const userAgent = "Nomerogram/2.18 (iPhone; iOS 13.7; Scale/2.00)";
class NomerogramProvider { class NomerogramProvider {
static async getGroups(number) { static async getGroups(number) {
try { try {
let timestamp = Math.floor(Date.now() / 1000); let timestamp = Math.floor(Date.now() / 1000);
let secretSource = appId + number + deviceId + from + timestamp + secretSuffix; let secretSource =
appId + number + deviceId + from + timestamp + secretSuffix;
let hash = createHash('sha256'); let hash = createHash("sha256");
hash.update(secretSource); hash.update(secretSource);
let secret = hash.digest('hex'); let secret = hash.digest("hex");
console.log('secret: ', secret); console.log("secret: ", secret);
let url = `${baseUrl}/group/list?from=${from}&carplate=${number}&timestamp=${timestamp}&secret=${secret}&app_id=${appId}&device_id=${deviceId}`; let url = `${baseUrl}/group/list?from=${from}&carplate=${number}&timestamp=${timestamp}&secret=${secret}&app_id=${appId}&device_id=${deviceId}`;
let result = await fetch(url, { let result = await fetch(url, {
timeout: 5000, timeout: 5000,
headers: { 'User-Agent': userAgent } headers: { "User-Agent": userAgent },
}); });
let json = await result.json(); let json = await result.json();
if(!json.success) { if (!json.success) {
console.log('Nomerogram error: ', json.message); console.log("Nomerogram error: ", json.message);
throw Error(json.message); throw Error(json.message);
//return []; //return [];
} }
console.log('Nomerogram found ads: ', json.data.groups.length); console.log("Nomerogram found ads: ", json.data.groups.length);
return json.data.groups.map(g => { return json.data.groups.flatMap((g) => {
return g.photos.map((p) => {
return { return {
id: g.group_id, url: p.src.default,
url: g.group_url, thumbnail: p.src.thumbnail,
price: g.price,
date: Utils.parseDate(g.date), date: Utils.parseDate(g.date),
mileage: g.mileage,
region: g.region_name,
city: g.city_name,
adDescription: g.description,
photos: g.photos.map(p => p.src.default)
}; };
}); });
} catch(ex) { });
console.log('Nomerogram error: ', ex.message); } catch (ex) {
console.log("Nomerogram error: ", ex.message);
ex.debugInfo = { nomerogram: DebugInfo.fromError(ex.message) }; ex.debugInfo = { nomerogram: DebugInfo.fromError(ex.message) };
throw ex; throw ex;
} }

View File

@ -1,49 +1,54 @@
import { Router } from 'express'; import { Router } from "express";
import Jwt from 'jsonwebtoken'; import Jwt from "jsonwebtoken";
import cors from 'cors'; import cors from "cors";
import AvtocodProvider from '../data_providers/avtocod.js'; import AvtocodProvider from "../data_providers/avtocod.js";
import Vin01Provider from '../data_providers/vin01.js'; import Vin01Provider from "../data_providers/vin01.js";
import Constants from '../data_providers/constants.js'; import Constants from "../data_providers/constants.js";
import RsaProvider from '../data_providers/rsa.js'; import RsaProvider from "../data_providers/rsa.js";
import NomerogramProvider from '../data_providers/nomerogram.js'; import NomerogramProvider from "../data_providers/nomerogram.js";
import Utils from '../utils/utils.js'; import Utils from "../utils/utils.js";
import { ObjectId } from 'mongodb'; import { ObjectId } from "mongodb";
import DebugInfo from '../models/DebugInfo.js'; import DebugInfo from "../models/DebugInfo.js";
import Vehicle from '../models/vehicle.js'; import Vehicle from "../models/vehicle.js";
import { TGProvider } from '../data_providers/tgprovider.js'; import { TGProvider } from "../data_providers/tgprovider.js";
const router = Router(); const router = Router();
const makeError = error => ({ success: false, error }); const makeError = (error) => ({ success: false, error });
router.post('/check', async (req, res) => { router.post("/check", async (req, res) => {
const number = req.body.number.replace(/ /g, '').toUpperCase(); const number = req.body.number.replace(/ /g, "").toUpperCase();
const { googleIdToken, forceUpdate, notes, events } = req.body; const { googleIdToken, forceUpdate, notes, events } = req.body;
const { email } = req.user; const { email } = req.user;
console.log(`=== checking number: ${number} ====================================`); console.log(
`=== checking number: ${number} ====================================`,
);
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let vehicles = await collection.find({ number }).toArray(); let vehicles = await collection.find({ number }).toArray();
if(vehicles.length > 0 && !forceUpdate) { if (vehicles.length > 0 && !forceUpdate) {
console.log('vehicle found in database'); console.log("vehicle found in database");
let updatedDate = Date.now(); let updatedDate = Date.now();
if(notes) { if (notes) {
Vehicle.mergeNotes(vehicles[0], notes); Vehicle.mergeNotes(vehicles[0], notes);
} }
if(events) { if (events) {
Vehicle.mergeEvents(vehicles[0], events); Vehicle.mergeEvents(vehicles[0], events);
} }
await collection.updateOne({ number }, { await collection.updateOne(
{ number },
{
$set: { $set: {
updatedDate, updatedDate,
events: vehicles[0].events, events: vehicles[0].events,
notes: vehicles[0].notes notes: vehicles[0].notes,
} },
}); },
);
vehicles[0].updatedDate = updatedDate; vehicles[0].updatedDate = updatedDate;
res.send({ success: true, data: vehicles[0] }); res.send({ success: true, data: vehicles[0] });
} else { } else {
@ -51,17 +56,22 @@ router.post('/check', async (req, res) => {
let autocodPromise = AvtocodProvider.getReport(number); let autocodPromise = AvtocodProvider.getReport(number);
let all = [autocodPromise]; let all = [autocodPromise];
if(googleIdToken) { if (googleIdToken) {
let vin01Promise = Vin01Provider.getReport(number, googleIdToken); let vin01Promise = Vin01Provider.getReport(
number,
googleIdToken,
);
all.push(vin01Promise); all.push(vin01Promise);
} else { } else {
all.push(Promise.reject({ all.push(
Promise.reject({
debugInfo: { debugInfo: {
vin01vin: DebugInfo.fromError('No auth token'), vin01vin: DebugInfo.fromError("No auth token"),
vin01history: DebugInfo.fromError('No auth token'), vin01history: DebugInfo.fromError("No auth token"),
vin01base: DebugInfo.fromError('No auth token') vin01base: DebugInfo.fromError("No auth token"),
} },
})); }),
);
} }
all.push(NomerogramProvider.getGroups(number)); all.push(NomerogramProvider.getGroups(number));
@ -69,30 +79,32 @@ router.post('/check', async (req, res) => {
let [autocod, vin01, nomerogram] = await Promise.allSettled(all); let [autocod, vin01, nomerogram] = await Promise.allSettled(all);
let vehicle = null; let vehicle = null;
if(autocod.status == 'rejected' && vin01.status == 'rejected') { if (autocod.status == "rejected" && vin01.status == "rejected") {
throw autocod.reason; throw autocod.reason;
} else if(vin01.status == 'rejected') { } else if (vin01.status == "rejected") {
vehicle = autocod.value; vehicle = autocod.value;
Object.assign(vehicle.debugInfo, vin01.reason.debugInfo); Object.assign(vehicle.debugInfo, vin01.reason.debugInfo);
} else if(autocod.status == 'rejected') { } else if (autocod.status == "rejected") {
vehicle = vin01.value; vehicle = vin01.value;
Object.assign(vehicle.debugInfo, autocod.reason.debugInfo); Object.assign(vehicle.debugInfo, autocod.reason.debugInfo);
if(!vehicle.brand?.name?.normalized) { if (!vehicle.brand?.name?.normalized) {
throw autocod.reason; throw autocod.reason;
} }
} else { } else {
vehicle = autocod.value; vehicle = autocod.value;
let vinMatch = false; let vinMatch = false;
if(vin01.value.vin1 && vehicle.vin1) { if (vin01.value.vin1 && vehicle.vin1) {
vinMatch = vin01.value.vin1.match(RegExp(vehicle.vin1.replace(/\*/g, '.'))); vinMatch = vin01.value.vin1.match(
RegExp(vehicle.vin1.replace(/\*/g, ".")),
);
} }
if(vehicle.vin1 && vinMatch) { if (vehicle.vin1 && vinMatch) {
vehicle.vin1 = vin01.value.vin1; vehicle.vin1 = vin01.value.vin1;
vehicle.vin2 = vin01.value.vin2; vehicle.vin2 = vin01.value.vin2;
vehicle.color = vin01.value.color; vehicle.color = vin01.value.color;
vehicle.ownershipPeriods = vin01.value.ownershipPeriods; vehicle.ownershipPeriods = vin01.value.ownershipPeriods;
} else if(!vinMatch) { } else if (!vinMatch) {
let vin01data = `${vin01.value.vin1} - ${vin01.value?.brand?.name?.original}`; let vin01data = `${vin01.value.vin1} - ${vin01.value?.brand?.name?.original}`;
let autocodData = `${autocod.value.vin1} - ${autocod.value.brand.name.original}`; let autocodData = `${autocod.value.vin1} - ${autocod.value.brand.name.original}`;
let warning = `Vin01 VIN (${vin01data}) doesn't match with avtocod's one (${autocodData})`; let warning = `Vin01 VIN (${vin01data}) doesn't match with avtocod's one (${autocodData})`;
@ -103,9 +115,12 @@ router.post('/check', async (req, res) => {
Object.assign(vehicle.debugInfo, vin01.value.debugInfo); Object.assign(vehicle.debugInfo, vin01.value.debugInfo);
} }
if(nomerogram.status == 'fulfilled') { if (nomerogram.status == "fulfilled") {
vehicle.ads = nomerogram.value; let photos = nomerogram.value;
Object.assign(vehicle.debugInfo, { nomerogram: new DebugInfo() }); vehicle.photos = vehicle.photos?.concat(photos) ?? photos;
Object.assign(vehicle.debugInfo, {
nomerogram: new DebugInfo(),
});
} else { } else {
Object.assign(vehicle.debugInfo, nomerogram.reason.debugInfo); Object.assign(vehicle.debugInfo, nomerogram.reason.debugInfo);
} }
@ -122,174 +137,194 @@ router.post('/check', async (req, res) => {
} }
// Merge new notes/events with old ones // Merge new notes/events with old ones
if(notes) { if (notes) {
vehicle.mergeNotes(notes); vehicle.mergeNotes(notes);
} }
if(events) { if (events) {
vehicle.mergeEvents(events); vehicle.mergeEvents(events);
} }
await collection.replaceOne({ number }, vehicle, { upsert: true }); await collection.replaceOne({ number }, vehicle, { upsert: true });
res.status(201).send({ success: true, data: vehicle }); res.status(201).send({ success: true, data: vehicle });
} catch(ex) { } catch (ex) {
res.send(makeError(ex.message)); res.send(makeError(ex.message));
console.error(ex); console.error(ex);
} }
} }
}); });
router.get('/', async (req, res) => { router.get("/", async (req, res) => {
const { email } = req.user; const { email } = req.user;
const { pageToken, sortBy, sortOrder } = req.query; const { pageToken, sortBy, sortOrder } = req.query;
let pageSize = parseInt(req.query.pageSize); let pageSize = parseInt(req.query.pageSize);
if(isNaN(pageSize)) { if (isNaN(pageSize)) {
pageSize = 50; pageSize = 50;
} }
try { try {
let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email); let finalQuery = Utils.makeVehiclesSearchQuery(req.query, email);
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let isAscending = sortOrder == 'ascending'; let isAscending = sortOrder == "ascending";
let response = {}; let response = {};
if(!pageToken) { if (!pageToken) {
response.count = await collection.countDocuments(finalQuery); response.count = await collection.countDocuments(finalQuery);
} else { } else {
let compareOperator = isAscending ? '$gt' : '$lt'; let compareOperator = isAscending ? "$gt" : "$lt";
let lastVehicle = await collection.findOne({ _id: new ObjectId(pageToken) }); let lastVehicle = await collection.findOne({
_id: new ObjectId(pageToken),
});
finalQuery.$or = [ finalQuery.$or = [
{ [sortBy]: { [compareOperator]: lastVehicle[sortBy] } }, { [sortBy]: { [compareOperator]: lastVehicle[sortBy] } },
{ {
[sortBy]: lastVehicle[sortBy], [sortBy]: lastVehicle[sortBy],
_id: { [compareOperator]: new ObjectId(pageToken) } _id: { [compareOperator]: new ObjectId(pageToken) },
} },
]; ];
} }
let vehicles = await collection.find(finalQuery).sort({ [sortBy]: isAscending ? 1 : -1 }).limit(pageSize).toArray(); let vehicles = await collection
if(vehicles.length == pageSize) { .find(finalQuery)
.sort({ [sortBy]: isAscending ? 1 : -1 })
.limit(pageSize)
.toArray();
if (vehicles.length == pageSize) {
response.pageToken = vehicles[vehicles.length - 1]._id; response.pageToken = vehicles[vehicles.length - 1]._id;
} }
response.items = vehicles; response.items = vehicles;
res.send({ success: true, data: response }); res.send({ success: true, data: response });
} catch(ex) { } catch (ex) {
res.send(makeError('Error reading vehicles from DB')); res.send(makeError("Error reading vehicles from DB"));
console.error(ex); console.error(ex);
} }
}); });
router.get('/report', async (req, res) => { router.get("/report", async (req, res) => {
const { number } = req.query; const { number } = req.query;
try { try {
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let vehicle = await collection.findOne({ number }); let vehicle = await collection.findOne({ number });
if(vehicle) { if (vehicle) {
res.send({ success: true, data: vehicle }); res.send({ success: true, data: vehicle });
} else { } else {
res.send(makeError('Vehicle not found')); res.send(makeError("Vehicle not found"));
} }
} catch(ex) { } catch (ex) {
res.send(makeError(ex.message)); res.send(makeError(ex.message));
console.error(ex); console.error(ex);
} }
}); });
router.get('/brands', async (req, res) => { router.get("/brands", async (req, res) => {
try { try {
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let brands = await collection.distinct('brand.name.normalized'); let brands = await collection.distinct("brand.name.normalized");
res.send({ success: true, data: brands.filter(Boolean) }); res.send({ success: true, data: brands.filter(Boolean) });
} catch(ex) { } catch (ex) {
res.send(makeError('Error reading vehicle brands from DB')); res.send(makeError("Error reading vehicle brands from DB"));
console.error(ex); console.error(ex);
} }
}); });
router.get('/models', async (req, res) => { router.get("/models", async (req, res) => {
try { try {
const { brand } = req.query; const { brand } = req.query;
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let models = await collection.distinct('model.name.normalized', { 'brand.name.normalized': brand }); let models = await collection.distinct("model.name.normalized", {
"brand.name.normalized": brand,
});
res.send({ success: true, data: models.filter(Boolean) }); res.send({ success: true, data: models.filter(Boolean) });
} catch(ex) { } catch (ex) {
res.send(makeError('Error reading vehicle models from DB')); res.send(makeError("Error reading vehicle models from DB"));
console.error(ex); console.error(ex);
} }
}); });
router.get('/colors', async (req, res) => { router.get("/colors", async (req, res) => {
try { try {
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let colors = await collection.distinct('color'); let colors = await collection.distinct("color");
res.send({ success: true, data: colors.filter(Boolean) }); res.send({ success: true, data: colors.filter(Boolean) });
} catch(ex) { } catch (ex) {
res.send(makeError('Error reading vehicle colors from DB')); res.send(makeError("Error reading vehicle colors from DB"));
console.error(ex); console.error(ex);
} }
}); });
router.get('/regions', (req, res) => { router.get("/regions", (req, res) => {
res.send({ success: true, data: Constants.regions }); res.send({ success: true, data: Constants.regions });
}); });
router.get('/years', async (req, res) => { router.get("/years", async (req, res) => {
try { try {
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let colors = await collection.distinct('year'); let colors = await collection.distinct("year");
res.send({ success: true, data: colors.filter(Boolean) }); res.send({ success: true, data: colors.filter(Boolean) });
} catch(ex) { } catch (ex) {
res.send(makeError('Error reading vehicle years from DB')); res.send(makeError("Error reading vehicle years from DB"));
console.error(ex); console.error(ex);
} }
}); });
router.get('/shared_report', cors({ origin: 'https://auto.aliencat.pro' }), async (req, res) => { router.get(
"/shared_report",
cors({ origin: "https://auto.aliencat.pro" }),
async (req, res) => {
try { try {
let { plateNumber } = Jwt.verify(req.query.token, process.env.JWT_SECRET_SHARED_REPORT); let { plateNumber } = Jwt.verify(
let collection = req.db.collection('vehicles'); req.query.token,
let vehicles = await collection.find({ number: plateNumber }).toArray(); process.env.JWT_SECRET_SHARED_REPORT,
if(vehicles.length > 0) { );
let collection = req.db.collection("vehicles");
let vehicles = await collection
.find({ number: plateNumber })
.toArray();
if (vehicles.length > 0) {
res.send({ success: true, data: vehicles[0] }); res.send({ success: true, data: vehicles[0] });
} else { } else {
res.send(makeError('Vehicle not found')); res.send(makeError("Vehicle not found"));
} }
} catch(ex) { } catch (ex) {
res.send(makeError(ex.message)); res.send(makeError(ex.message));
console.error(ex); console.error(ex);
} }
}); },
);
router.post('/checkOsago', async (req, res) => { router.post("/checkOsago", async (req, res) => {
try { try {
const { number, vin, date, token } = req.body; const { number, vin, date, token } = req.body;
let result = await RsaProvider.checkOsago(number, vin, date, token); let result = await RsaProvider.checkOsago(number, vin, date, token);
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let filter = number ? { number } : { vin1: vin }; let filter = number ? { number } : { vin1: vin };
await collection.updateOne(filter, { $push: { osagoContracts: result } }); await collection.updateOne(filter, {
$push: { osagoContracts: result },
});
let vehicle = await collection.findOne(filter); let vehicle = await collection.findOne(filter);
if(vehicle) { if (vehicle) {
res.send({ success: true, data: vehicle }); res.send({ success: true, data: vehicle });
} else { } else {
res.status(204).send(makeError('There is no vehicle with such plate number or VIN')); res.status(204).send(
makeError("There is no vehicle with such plate number or VIN"),
);
} }
} catch(ex) { } catch (ex) {
res.send(makeError(ex.message)); res.send(makeError(ex.message));
console.error(ex); console.error(ex);
} }
}); });
router.post('/checkGbTg', async (req, res) => { router.post("/checkGbTg", async (req, res) => {
let tgProvider = null; let tgProvider = null;
try { try {
const number = req.body.number.replace(/ /g, '').toUpperCase(); const number = req.body.number.replace(/ /g, "").toUpperCase();
const token = req.body.token; const token = req.body.token;
tgProvider = new TGProvider(); tgProvider = new TGProvider();
@ -297,49 +332,55 @@ router.post('/checkGbTg', async (req, res) => {
let report = await tgProvider.getReport(number, token); let report = await tgProvider.getReport(number, token);
await tgProvider.close(); await tgProvider.close();
if(!report?.generalInfo && !report?.insurance) { if (!report?.generalInfo && !report?.insurance) {
res.send(makeError('No data found')); res.send(makeError("No data found"));
return; return;
} }
let collection = req.db.collection('vehicles'); let collection = req.db.collection("vehicles");
let vehicle = await collection.findOne({ number }); let vehicle = await collection.findOne({ number });
if(vehicle) { if (vehicle) {
let vinRegex = RegExp(vehicle.vin1.replace(/\*/g, '.')); let vinRegex = RegExp(vehicle.vin1.replace(/\*/g, "."));
if(report?.generalInfo?.vin?.match(vinRegex)) { if (report?.generalInfo?.vin?.match(vinRegex)) {
let updatedFields = { let updatedFields = {
vin1: report.generalInfo.vin, vin1: report.generalInfo.vin,
color: report.generalInfo.color, color: report.generalInfo.color,
sts: report.generalInfo.sts, sts: report.generalInfo.sts,
updatedDate: Date.now() updatedDate: Date.now(),
}; };
if(report.insurance) { if (report.insurance) {
let osagoFound = vehicle.osagoContracts?.some(elem => { let osagoFound =
return elem.number = report.insurance.number; vehicle.osagoContracts?.some((elem) => {
return (elem.number = report.insurance.number);
}) ?? false; }) ?? false;
if(!osagoFound) { if (!osagoFound) {
await collection.updateOne({ number }, { $push: { osagoContracts: report.insurance } }); await collection.updateOne(
{ number },
{ $push: { osagoContracts: report.insurance } },
);
} }
} }
if(report.ownershipPeriods) { if (report.ownershipPeriods) {
updatedFields.ownershipPeriods = report.ownershipPeriods; updatedFields.ownershipPeriods = report.ownershipPeriods;
} }
await collection.updateOne({ number }, { $set: updatedFields }); await collection.updateOne({ number }, { $set: updatedFields });
vehicle = await collection.findOne({ number }); vehicle = await collection.findOne({ number });
res.send({ success: true, data: Object.assign(vehicle, updatedFields) }); res.send({
success: true,
data: Object.assign(vehicle, updatedFields),
});
} else { } else {
res.send(makeError('Vehicle doesn\'t match')); res.send(makeError("Vehicle doesn't match"));
} }
} else { } else {
res.send(makeError('Vehicle not found')); res.send(makeError("Vehicle not found"));
} }
} catch (ex) {
} catch(ex) {
res.send(makeError(ex.message)); res.send(makeError(ex.message));
console.error(ex); console.error(ex);
await tgProvider.close(); await tgProvider.close();