From 105bd25dc2f382f368b9eec29be8b08969bfc2bb Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Thu, 15 Aug 2024 19:34:02 +0300 Subject: [PATCH] Adding photos from ads to general photos section --- data_providers/nomerogram.js | 71 ++++---- routes/vehicles.js | 317 ++++++++++++++++++++--------------- 2 files changed, 213 insertions(+), 175 deletions(-) diff --git a/data_providers/nomerogram.js b/data_providers/nomerogram.js index 0012bb4..b834652 100644 --- a/data_providers/nomerogram.js +++ b/data_providers/nomerogram.js @@ -1,59 +1,56 @@ -import { createHash } from 'crypto'; -import Utils from '../utils/utils.js'; -import DebugInfo from '../models/DebugInfo.js'; +import { createHash } from "crypto"; +import Utils from "../utils/utils.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 appId = 'p15'; -const deviceId = '01b854631cb28e175ffbcccf6114acc3'; -const from = 'search'; -const userAgent = 'Nomerogram/2.18 (iPhone; iOS 13.7; Scale/2.00)'; +const secretSuffix = "queivoo1ieNgae2e"; +const appId = "p15"; +const deviceId = "01b854631cb28e175ffbcccf6114acc3"; +const from = "search"; +const userAgent = "Nomerogram/2.18 (iPhone; iOS 13.7; Scale/2.00)"; class NomerogramProvider { static async getGroups(number) { try { let timestamp = Math.floor(Date.now() / 1000); - let secretSource = appId + number + deviceId + from + timestamp + secretSuffix; - - let hash = createHash('sha256'); + let secretSource = + appId + number + deviceId + from + timestamp + secretSuffix; + + let hash = createHash("sha256"); hash.update(secretSource); - let secret = hash.digest('hex'); - console.log('secret: ', secret); - + let secret = hash.digest("hex"); + console.log("secret: ", secret); + let url = `${baseUrl}/group/list?from=${from}&carplate=${number}×tamp=${timestamp}&secret=${secret}&app_id=${appId}&device_id=${deviceId}`; - let result = await fetch(url, { + let result = await fetch(url, { timeout: 5000, - headers: { 'User-Agent': userAgent } + headers: { "User-Agent": userAgent }, }); let json = await result.json(); - - if(!json.success) { - console.log('Nomerogram error: ', json.message); + + if (!json.success) { + console.log("Nomerogram error: ", json.message); throw Error(json.message); //return []; } - - console.log('Nomerogram found ads: ', json.data.groups.length); - return json.data.groups.map(g => { - return { - id: g.group_id, - url: g.group_url, - price: g.price, - 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) - }; + + console.log("Nomerogram found ads: ", json.data.groups.length); + return json.data.groups.flatMap((g) => { + return g.photos.map((p) => { + return { + url: p.src.default, + thumbnail: p.src.thumbnail, + date: Utils.parseDate(g.date), + }; + }); }); - } catch(ex) { - console.log('Nomerogram error: ', ex.message); + } catch (ex) { + console.log("Nomerogram error: ", ex.message); ex.debugInfo = { nomerogram: DebugInfo.fromError(ex.message) }; throw ex; } } } -export default NomerogramProvider; \ No newline at end of file +export default NomerogramProvider; diff --git a/routes/vehicles.js b/routes/vehicles.js index 516431f..9038d27 100644 --- a/routes/vehicles.js +++ b/routes/vehicles.js @@ -1,49 +1,54 @@ -import { Router } from 'express'; -import Jwt from 'jsonwebtoken'; -import cors from 'cors'; -import AvtocodProvider from '../data_providers/avtocod.js'; -import Vin01Provider from '../data_providers/vin01.js'; -import Constants from '../data_providers/constants.js'; -import RsaProvider from '../data_providers/rsa.js'; -import NomerogramProvider from '../data_providers/nomerogram.js'; -import Utils from '../utils/utils.js'; -import { ObjectId } from 'mongodb'; -import DebugInfo from '../models/DebugInfo.js'; -import Vehicle from '../models/vehicle.js'; -import { TGProvider } from '../data_providers/tgprovider.js'; +import { Router } from "express"; +import Jwt from "jsonwebtoken"; +import cors from "cors"; +import AvtocodProvider from "../data_providers/avtocod.js"; +import Vin01Provider from "../data_providers/vin01.js"; +import Constants from "../data_providers/constants.js"; +import RsaProvider from "../data_providers/rsa.js"; +import NomerogramProvider from "../data_providers/nomerogram.js"; +import Utils from "../utils/utils.js"; +import { ObjectId } from "mongodb"; +import DebugInfo from "../models/DebugInfo.js"; +import Vehicle from "../models/vehicle.js"; +import { TGProvider } from "../data_providers/tgprovider.js"; const router = Router(); -const makeError = error => ({ success: false, error }); +const makeError = (error) => ({ success: false, error }); -router.post('/check', async (req, res) => { - const number = req.body.number.replace(/ /g, '').toUpperCase(); +router.post("/check", async (req, res) => { + const number = req.body.number.replace(/ /g, "").toUpperCase(); const { googleIdToken, forceUpdate, notes, events } = req.body; 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(); - if(vehicles.length > 0 && !forceUpdate) { - console.log('vehicle found in database'); + if (vehicles.length > 0 && !forceUpdate) { + console.log("vehicle found in database"); let updatedDate = Date.now(); - if(notes) { + if (notes) { Vehicle.mergeNotes(vehicles[0], notes); } - - if(events) { + + if (events) { Vehicle.mergeEvents(vehicles[0], events); } - await collection.updateOne({ number }, { - $set: { - updatedDate, - events: vehicles[0].events, - notes: vehicles[0].notes - } - }); + await collection.updateOne( + { number }, + { + $set: { + updatedDate, + events: vehicles[0].events, + notes: vehicles[0].notes, + }, + }, + ); vehicles[0].updatedDate = updatedDate; res.send({ success: true, data: vehicles[0] }); } else { @@ -51,17 +56,22 @@ router.post('/check', async (req, res) => { let autocodPromise = AvtocodProvider.getReport(number); let all = [autocodPromise]; - if(googleIdToken) { - let vin01Promise = Vin01Provider.getReport(number, googleIdToken); + if (googleIdToken) { + let vin01Promise = Vin01Provider.getReport( + number, + googleIdToken, + ); all.push(vin01Promise); } else { - all.push(Promise.reject({ - debugInfo: { - vin01vin: DebugInfo.fromError('No auth token'), - vin01history: DebugInfo.fromError('No auth token'), - vin01base: DebugInfo.fromError('No auth token') - } - })); + all.push( + Promise.reject({ + debugInfo: { + vin01vin: DebugInfo.fromError("No auth token"), + vin01history: DebugInfo.fromError("No auth token"), + vin01base: DebugInfo.fromError("No auth token"), + }, + }), + ); } all.push(NomerogramProvider.getGroups(number)); @@ -69,30 +79,32 @@ router.post('/check', async (req, res) => { let [autocod, vin01, nomerogram] = await Promise.allSettled(all); let vehicle = null; - if(autocod.status == 'rejected' && vin01.status == 'rejected') { + if (autocod.status == "rejected" && vin01.status == "rejected") { throw autocod.reason; - } else if(vin01.status == 'rejected') { + } else if (vin01.status == "rejected") { vehicle = autocod.value; Object.assign(vehicle.debugInfo, vin01.reason.debugInfo); - } else if(autocod.status == 'rejected') { + } else if (autocod.status == "rejected") { vehicle = vin01.value; Object.assign(vehicle.debugInfo, autocod.reason.debugInfo); - if(!vehicle.brand?.name?.normalized) { + if (!vehicle.brand?.name?.normalized) { throw autocod.reason; } } else { vehicle = autocod.value; let vinMatch = false; - if(vin01.value.vin1 && vehicle.vin1) { - vinMatch = vin01.value.vin1.match(RegExp(vehicle.vin1.replace(/\*/g, '.'))); + if (vin01.value.vin1 && vehicle.vin1) { + vinMatch = vin01.value.vin1.match( + RegExp(vehicle.vin1.replace(/\*/g, ".")), + ); } - - if(vehicle.vin1 && vinMatch) { + + if (vehicle.vin1 && vinMatch) { vehicle.vin1 = vin01.value.vin1; vehicle.vin2 = vin01.value.vin2; vehicle.color = vin01.value.color; vehicle.ownershipPeriods = vin01.value.ownershipPeriods; - } else if(!vinMatch) { + } else if (!vinMatch) { let vin01data = `${vin01.value.vin1} - ${vin01.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})`; @@ -103,9 +115,12 @@ router.post('/check', async (req, res) => { Object.assign(vehicle.debugInfo, vin01.value.debugInfo); } - if(nomerogram.status == 'fulfilled') { - vehicle.ads = nomerogram.value; - Object.assign(vehicle.debugInfo, { nomerogram: new DebugInfo() }); + if (nomerogram.status == "fulfilled") { + let photos = nomerogram.value; + vehicle.photos = vehicle.photos?.concat(photos) ?? photos; + Object.assign(vehicle.debugInfo, { + nomerogram: new DebugInfo(), + }); } else { Object.assign(vehicle.debugInfo, nomerogram.reason.debugInfo); } @@ -122,174 +137,194 @@ router.post('/check', async (req, res) => { } // Merge new notes/events with old ones - if(notes) { + if (notes) { vehicle.mergeNotes(notes); } - - if(events) { + + if (events) { vehicle.mergeEvents(events); } await collection.replaceOne({ number }, vehicle, { upsert: true }); res.status(201).send({ success: true, data: vehicle }); - } catch(ex) { + } catch (ex) { res.send(makeError(ex.message)); console.error(ex); } } }); -router.get('/', async (req, res) => { +router.get("/", async (req, res) => { const { email } = req.user; const { pageToken, sortBy, sortOrder } = req.query; - + let pageSize = parseInt(req.query.pageSize); - if(isNaN(pageSize)) { + if (isNaN(pageSize)) { pageSize = 50; } try { 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 = {}; - if(!pageToken) { + if (!pageToken) { response.count = await collection.countDocuments(finalQuery); } else { - let compareOperator = isAscending ? '$gt' : '$lt'; - let lastVehicle = await collection.findOne({ _id: new ObjectId(pageToken) }); + let compareOperator = isAscending ? "$gt" : "$lt"; + let lastVehicle = await collection.findOne({ + _id: new ObjectId(pageToken), + }); finalQuery.$or = [ { [sortBy]: { [compareOperator]: 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(); - if(vehicles.length == pageSize) { + let vehicles = await collection + .find(finalQuery) + .sort({ [sortBy]: isAscending ? 1 : -1 }) + .limit(pageSize) + .toArray(); + if (vehicles.length == pageSize) { response.pageToken = vehicles[vehicles.length - 1]._id; } response.items = vehicles; res.send({ success: true, data: response }); - } catch(ex) { - res.send(makeError('Error reading vehicles from DB')); + } catch (ex) { + res.send(makeError("Error reading vehicles from DB")); console.error(ex); } }); -router.get('/report', async (req, res) => { +router.get("/report", async (req, res) => { const { number } = req.query; try { - let collection = req.db.collection('vehicles'); + let collection = req.db.collection("vehicles"); let vehicle = await collection.findOne({ number }); - if(vehicle) { + if (vehicle) { res.send({ success: true, data: vehicle }); } else { - res.send(makeError('Vehicle not found')); + res.send(makeError("Vehicle not found")); } - } catch(ex) { + } catch (ex) { res.send(makeError(ex.message)); console.error(ex); } }); -router.get('/brands', async (req, res) => { +router.get("/brands", async (req, res) => { try { - let collection = req.db.collection('vehicles'); - let brands = await collection.distinct('brand.name.normalized'); + let collection = req.db.collection("vehicles"); + let brands = await collection.distinct("brand.name.normalized"); res.send({ success: true, data: brands.filter(Boolean) }); - } catch(ex) { - res.send(makeError('Error reading vehicle brands from DB')); + } catch (ex) { + res.send(makeError("Error reading vehicle brands from DB")); console.error(ex); } }); -router.get('/models', async (req, res) => { +router.get("/models", async (req, res) => { try { const { brand } = req.query; - let collection = req.db.collection('vehicles'); - let models = await collection.distinct('model.name.normalized', { 'brand.name.normalized': brand }); + let collection = req.db.collection("vehicles"); + let models = await collection.distinct("model.name.normalized", { + "brand.name.normalized": brand, + }); res.send({ success: true, data: models.filter(Boolean) }); - } catch(ex) { - res.send(makeError('Error reading vehicle models from DB')); + } catch (ex) { + res.send(makeError("Error reading vehicle models from DB")); console.error(ex); } }); -router.get('/colors', async (req, res) => { +router.get("/colors", async (req, res) => { try { - let collection = req.db.collection('vehicles'); - let colors = await collection.distinct('color'); + let collection = req.db.collection("vehicles"); + let colors = await collection.distinct("color"); res.send({ success: true, data: colors.filter(Boolean) }); - } catch(ex) { - res.send(makeError('Error reading vehicle colors from DB')); + } catch (ex) { + res.send(makeError("Error reading vehicle colors from DB")); console.error(ex); } }); -router.get('/regions', (req, res) => { +router.get("/regions", (req, res) => { res.send({ success: true, data: Constants.regions }); }); -router.get('/years', async (req, res) => { +router.get("/years", async (req, res) => { try { - let collection = req.db.collection('vehicles'); - let colors = await collection.distinct('year'); + let collection = req.db.collection("vehicles"); + let colors = await collection.distinct("year"); res.send({ success: true, data: colors.filter(Boolean) }); - } catch(ex) { - res.send(makeError('Error reading vehicle years from DB')); + } catch (ex) { + res.send(makeError("Error reading vehicle years from DB")); console.error(ex); } }); -router.get('/shared_report', cors({ origin: 'https://auto.aliencat.pro' }), async (req, res) => { - try { - let { plateNumber } = Jwt.verify(req.query.token, process.env.JWT_SECRET_SHARED_REPORT); - 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] }); - } else { - res.send(makeError('Vehicle not found')); +router.get( + "/shared_report", + cors({ origin: "https://auto.aliencat.pro" }), + async (req, res) => { + try { + let { plateNumber } = Jwt.verify( + req.query.token, + process.env.JWT_SECRET_SHARED_REPORT, + ); + 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] }); + } else { + res.send(makeError("Vehicle not found")); + } + } catch (ex) { + res.send(makeError(ex.message)); + console.error(ex); } - } catch(ex) { - res.send(makeError(ex.message)); - console.error(ex); - } -}); + }, +); -router.post('/checkOsago', async (req, res) => { +router.post("/checkOsago", async (req, res) => { try { const { number, vin, date, token } = req.body; 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 }; - await collection.updateOne(filter, { $push: { osagoContracts: result } }); + await collection.updateOne(filter, { + $push: { osagoContracts: result }, + }); let vehicle = await collection.findOne(filter); - if(vehicle) { + if (vehicle) { res.send({ success: true, data: vehicle }); } 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)); console.error(ex); } }); -router.post('/checkGbTg', async (req, res) => { - +router.post("/checkGbTg", async (req, res) => { let tgProvider = null; try { - const number = req.body.number.replace(/ /g, '').toUpperCase(); + const number = req.body.number.replace(/ /g, "").toUpperCase(); const token = req.body.token; tgProvider = new TGProvider(); @@ -297,49 +332,55 @@ router.post('/checkGbTg', async (req, res) => { let report = await tgProvider.getReport(number, token); await tgProvider.close(); - if(!report?.generalInfo && !report?.insurance) { - res.send(makeError('No data found')); + if (!report?.generalInfo && !report?.insurance) { + res.send(makeError("No data found")); return; } - let collection = req.db.collection('vehicles'); + let collection = req.db.collection("vehicles"); let vehicle = await collection.findOne({ number }); - if(vehicle) { - let vinRegex = RegExp(vehicle.vin1.replace(/\*/g, '.')); + if (vehicle) { + let vinRegex = RegExp(vehicle.vin1.replace(/\*/g, ".")); - if(report?.generalInfo?.vin?.match(vinRegex)) { + if (report?.generalInfo?.vin?.match(vinRegex)) { let updatedFields = { vin1: report.generalInfo.vin, color: report.generalInfo.color, sts: report.generalInfo.sts, - updatedDate: Date.now() + updatedDate: Date.now(), }; - if(report.insurance) { - let osagoFound = vehicle.osagoContracts?.some(elem => { - return elem.number = report.insurance.number; - }) ?? false; - if(!osagoFound) { - await collection.updateOne({ number }, { $push: { osagoContracts: report.insurance } }); + if (report.insurance) { + let osagoFound = + vehicle.osagoContracts?.some((elem) => { + return (elem.number = report.insurance.number); + }) ?? false; + if (!osagoFound) { + await collection.updateOne( + { number }, + { $push: { osagoContracts: report.insurance } }, + ); } } - if(report.ownershipPeriods) { + if (report.ownershipPeriods) { updatedFields.ownershipPeriods = report.ownershipPeriods; } await collection.updateOne({ number }, { $set: updatedFields }); vehicle = await collection.findOne({ number }); - res.send({ success: true, data: Object.assign(vehicle, updatedFields) }); + res.send({ + success: true, + data: Object.assign(vehicle, updatedFields), + }); } else { - res.send(makeError('Vehicle doesn\'t match')); + res.send(makeError("Vehicle doesn't match")); } } else { - res.send(makeError('Vehicle not found')); + res.send(makeError("Vehicle not found")); } - - } catch(ex) { + } catch (ex) { res.send(makeError(ex.message)); console.error(ex); await tgProvider.close();