Migrating to ES modules. Adding TG client

This commit is contained in:
Selim Mustafaev 2024-03-16 15:02:32 +03:00
parent 6f03bf49c5
commit d0a0fcb105
26 changed files with 559 additions and 195 deletions

View File

@ -10,10 +10,11 @@ PRIVATE_KEY_PATH = "/path/to/privkey.pem"
# Database
DB_NAME = ""
DB_USER_NAME = ""
DB_USER_PASSWORD = ""
DB_SERVER = ""
MONGO_CONNECTION_STRING = "mongodb+srv://$DB_USER_NAME:$DB_USER_PASSWORD@$DB_SERVER/autocatdev?retryWrites=true&w=majority"
MONGO_CONNECTION_STRING = "mongodb+srv://$DB_USER_NAME:$DB_USER_PASSWORD@$DB_SERVER"
# JWT secrets

View File

@ -25,5 +25,8 @@ module.exports = {
'always'
],
'no-console': 0
},
'parserOptions': {
'sourceType': 'module'
}
};

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
.DS_Store
_td_database/
node_modules/
.env

View File

@ -1,13 +1,13 @@
const crypto = require('crypto');
const Vehicle = require('../models/vehicle');
const DebugInfo = require('../models/DebugInfo');
const { Centrifuge } = require('centrifuge');
const WebSocket = require('ws');
import { createHash, createDecipheriv } from 'crypto';
import Vehicle from '../models/vehicle.js';
import DebugInfo from '../models/DebugInfo.js';
import { Centrifuge } from 'centrifuge';
import WebSocket from 'ws';
const baseUrl = 'https://avtocod.ru/api/v3';
const tokenRefreshUrl = 'https://avtocod.ru/api/centrifuge/refresh';
let deviceToken = crypto.createHash('sha256').update(Date.now().toString()).digest().toString('hex');
let deviceToken = createHash('sha256').update(Date.now().toString()).digest().toString('hex');
const myWs = function (options) {
return class wsClass extends WebSocket {
@ -37,9 +37,9 @@ function decryptReport(report, hash) {
let iv = Buffer.from(encryptedObject.iv, 'base64');
let data = Buffer.from(encryptedObject.value, 'base64');
let key = crypto.createHash('sha256').update(hash).digest();
let key = createHash('sha256').update(hash).digest();
let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decipher = createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(data);
decrypted = Buffer.concat([decrypted, decipher.final()]);
@ -147,4 +147,4 @@ class AvtocodProvider {
}
}
module.exports = AvtocodProvider;
export default AvtocodProvider;

View File

@ -255,6 +255,6 @@ const regions = [
{ name: 'Чеченская республика', codes: [20, 95]},
];
module.exports = {
export default {
organs, ogr, typeAuto, typeOperation, regions
};

View File

@ -1,7 +1,7 @@
const crypto = require('crypto');
const Utils = require('../utils/utils');
const utf8 = require('utf8');
const DebugInfo = require('../models/DebugInfo');
import { createHash } from 'crypto';
import Utils from '../utils/utils.js';
import Utf8 from 'utf8';
import DebugInfo from '../models/DebugInfo.js';
const baseUrl = 'https://www.nomerogram.ru/api/v1.1';
@ -17,13 +17,13 @@ class NomerogramProvider {
let timestamp = Math.floor(Date.now() / 1000);
let secretSource = appId + number + deviceId + from + timestamp + secretSuffix;
let hash = crypto.createHash('sha256');
let hash = createHash('sha256');
hash.update(secretSource);
let secret = hash.digest('hex');
console.log('secret: ', secret);
let url = `${baseUrl}/group/list?from=${from}&carplate=${number}&timestamp=${timestamp}&secret=${secret}&app_id=${appId}&device_id=${deviceId}`;
let result = await fetch(utf8.encode(url), {
let result = await fetch(Utf8.encode(url), {
timeout: 5000,
headers: { 'User-Agent': userAgent }
});
@ -57,4 +57,4 @@ class NomerogramProvider {
}
}
module.exports = NomerogramProvider;
export default NomerogramProvider;

View File

@ -1,7 +1,7 @@
const https = require('https');
const parser = require('node-html-parser');
import { Agent } from 'https';
import { parse } from 'node-html-parser';
const httpsAgent = new https.Agent({
const httpsAgent = new Agent({
rejectUnauthorized: false
});
@ -50,7 +50,7 @@ class RsaProvider {
}
static parseReport(html) {
let root = parser.parse(html);
let root = parse(html);
if(!root) {
throw Error('Failed to parse dkbm response');
}
@ -91,4 +91,4 @@ class RsaProvider {
}
}
module.exports = RsaProvider;
export default RsaProvider;

108
data_providers/tgclient.js Normal file
View File

@ -0,0 +1,108 @@
import tdl from 'tdl';
import { platform } from 'node:process';
class TGClient {
static {
let libdir = null;
if(platform == 'linux') {
libdir = './node_modules/prebuilt-tdlib/prebuilds/tdlib-linux-x64';
} else if(platform == 'darwin') {
libdir = './node_modules/prebuilt-tdlib/prebuilds/tdlib-macos';
}
tdl.configure({ libdir });
}
constructor(apiId, apiHash) {
this.client = tdl.createClient({
apiId: apiId,
apiHash: apiHash
});
this.client.on('error', console.error);
this.client.on('update', update => {
//console.log('update: ', update);
switch(update._) {
case 'updateMessageSendSucceeded':
this.sendTasks.get(update.old_message_id)?.resolve(update.message);
this.sendTasks.delete(update.old_message_id);
break;
case 'updateMessageSendFailed':
this.sendTasks.get(update.old_message_id)?.reject(Error(update.error_message));
this.sendTasks.delete(update.old_message_id);
break;
case 'updateNewMessage':
this.newMessageCallback?.(update.message);
break;
}
});
this.sendTasks = new Map();
}
onNewMessage(callback) {
this.newMessageCallback = callback;
}
waitAsync(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async login() {
await this.client.login();
}
async close() {
await this.client.close();
}
async getMe() {
return await this.client.invoke({ _: 'getMe'});
}
async findChat(name) {
return await this.client.invoke({
_: 'searchPublicChat',
username: name
});
}
async getSavedMessagesChat() {
let me = await this.getMe();
return await this.client.invoke({
_: 'createPrivateChat',
user_id: me.id
});
}
async sendMessage(chat, text) {
let message = await this.client.invoke({
_: 'sendMessage',
chat_id: chat.id,
input_message_content: {
_: 'inputMessageText',
text: {
_: 'formattedText',
text
}
}
});
let sendStatusTask = Promise.withResolvers();
this.sendTasks.set(message.id, sendStatusTask);
return await sendStatusTask.promise;
}
async viewMessage(id, chatId) {
await this.client.invoke({
_: 'viewMessages',
chat_id: chatId,
message_ids: [ id ]
});
}
}
export { TGClient };

View File

@ -0,0 +1,80 @@
import { TGClient } from './tgclient.js';
class TGProvider {
constructor() {
this.tgClient = new TGClient(869171, 'c3731f831b212a314f71172daf233f9d');
this.checksMap = new Map();
this.tgClient.onNewMessage(message => {
if(message.chat_id == this.chat.id) {
let messageText = message?.content?.text?.text;
if(messageText && messageText.includes('#️⃣')) {
let number = this.findFirst(messageText, /Номер: (.*)\n/);
if(number) {
this.checksMap.get(number).resolve({
id: message.id,
text: messageText
});
}
}
}
});
//this.init();
}
findFirst(string, regex) {
let result = string.match(regex);
if(result && result.length > 1) {
return result[1];
} else {
return null;
}
}
async init() {
await this.tgClient.login();
this.chat = await this.tgClient.findChat('@l0r3m1psum_bot');
}
async close() {
await this.tgClient.close();
}
async getReport(number) {
try {
await this.tgClient.sendMessage(this.chat, number);
let waitResponseTask = Promise.withResolvers();
this.checksMap.set(number, waitResponseTask);
setTimeout(() => {
waitResponseTask.reject(Error('TG report timeout'));
}, 10000);
let { id, text } = await waitResponseTask.promise;
await this.tgClient.viewMessage(id, this.chat.id);
return this.parseReport(text);
} finally {
this.checksMap.delete(number);
}
}
parseReport(text) {
let number = this.findFirst(text, /Номер: (.*)\n/);
let vin = this.findFirst(text, /VIN: (.*)\n/);
let owner = this.findFirst(text, /Владелец: (.*)\n/);
let year = this.findFirst(text, /Год: (.*)\n/);
let color = this.findFirst(text, /Цвет: (.*)\n/);
let sts = this.findFirst(text, /СТС: (.*)\n/);
return {
number,
vin,
owner,
year,
color,
sts
};
}
}
export { TGProvider };

View File

@ -1,7 +1,7 @@
const AbortController = require('abort-controller');
const DebugInfo = require('../models/DebugInfo');
const Vehicle = require('../models/vehicle');
const Utils = require('../utils/utils');
import AbortController from 'abort-controller';
import DebugInfo from '../models/DebugInfo.js';
import Vehicle from '../models/vehicle.js';
import Utils from '../utils/utils.js';
const baseUrl = 'https://vin01.ru/v2';
const reportBaseUrl = `${baseUrl}/gibddApp.php`;
@ -157,4 +157,4 @@ class Vin01Provider {
}
}
module.exports = Vin01Provider;
export default Vin01Provider;

View File

@ -1,21 +1,21 @@
const express = require('express');
const bodyParser = require('body-parser');
const expressMongoDb = require('./middleware/mongo');
const users = require('./routes/user');
const vehicles = require('./routes/vehicles');
const events = require('./routes/events');
const notes = require('./routes/notes');
const app = express();
const bearerToken = require('express-bearer-token');
const jwt = require('./middleware/jwt');
const https = require('https');
const fs = require('fs');
const compression = require('compression');
const dotenv = require('dotenv');
const dotenvExpand = require('dotenv-expand');
const responseTime = require('response-time');
import express from 'express';
import expressMongoDb from './middleware/mongo.js';
import users from './routes/user.js';
import vehicles from './routes/vehicles.js';
import events from './routes/events.js';
import notes from './routes/notes.js';
import bearerToken from 'express-bearer-token';
import jwt from './middleware/jwt.js';
import { createServer } from 'https';
import { readFileSync } from 'fs';
import compression from 'compression';
import { config } from 'dotenv';
import dotenvExpand from 'dotenv-expand';
import responseTime from 'response-time';
let dotenvConf = dotenv.config();
const app = express();
let dotenvConf = config();
dotenvExpand(dotenvConf);
app.use(responseTime(function (req, res, time) {
@ -23,7 +23,7 @@ app.use(responseTime(function (req, res, time) {
}));
app.use(compression());
app.use(bodyParser.json());
app.use(express.json());
app.use(expressMongoDb(process.env.MONGO_CONNECTION_STRING));
app.use(bearerToken());
app.use(jwt({ secret: process.env.JWT_SECRET_AUTH, exclude: ['/user/signup', '/user/login', '/vehicles/shared_report'] }));
@ -39,9 +39,9 @@ app.use((req, res) => {
});
if(process.env.NODE_ENV == 'production') {
const httpsServer = https.createServer({
key: fs.readFileSync(process.env.PRIVATE_KEY_PATH),
cert: fs.readFileSync(process.env.CERT_PATH)
const httpsServer = createServer({
key: readFileSync(process.env.PRIVATE_KEY_PATH),
cert: readFileSync(process.env.CERT_PATH)
}, app);
httpsServer.listen(8443);
} else {

View File

@ -1,6 +1,6 @@
const jsonwebtoken = require('jsonwebtoken');
import Jwt from 'jsonwebtoken';
module.exports = function (options) {
export default function (options) {
return function jwt(req, res, next) {
if('exclude' in options && options.exclude.includes(req.path)) {
next();
@ -13,7 +13,7 @@ module.exports = function (options) {
let scheme = parts[0];
let token = parts[1];
if (/^Bearer$/i.test(scheme)) {
jsonwebtoken.verify(token, options.secret, (error, decoded) => {
Jwt.verify(token, options.secret, (error, decoded) => {
if(error) {
res.status(401).send({ success: false, error: error.message });
console.error(error);
@ -35,4 +35,4 @@ module.exports = function (options) {
console.error('Missing authorization header');
}
};
};
}

View File

@ -1,6 +1,6 @@
let MongoClient = require('mongodb').MongoClient;
import { MongoClient } from 'mongodb';
module.exports = function (uri) {
export default function expressMongoDb(uri) {
if (typeof uri !== 'string') {
throw new TypeError('Expected uri to be a string');
}
@ -14,7 +14,7 @@ module.exports = function (uri) {
connection
.then(function (client) {
req['db'] = client.db('autocat');
req['db'] = client.db(process.env.DB_NAME);
next();
})
.catch(function (err) {
@ -22,4 +22,4 @@ module.exports = function (uri) {
next(err);
});
};
};
}

View File

@ -1,7 +1,7 @@
class DebugInfo {
status
fields
error
status;
fields;
error;
constructor() {
this.status = 0;
@ -29,4 +29,4 @@ class DebugInfo {
}
}
module.exports = DebugInfo;
export default DebugInfo;

View File

@ -1,9 +1,9 @@
class Engine {
number
volume
type
power
fuelType
number;
volume;
type;
power;
fuelType;
}
module.exports = Engine;
export default Engine;

View File

@ -1,11 +1,11 @@
class Event {
id
date
latitude
longitude
speed
direction
address
id;
date;
latitude;
longitude;
speed;
direction;
address;
}
module.exports = Event;
export default Event;

View File

@ -1,8 +1,8 @@
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');
import { createHash } from 'crypto';
import { v4 as uuidv4 } from 'uuid';
const hash = Symbol();
const sha256 = text => crypto.createHash('sha256').update(text).digest('base64');
const sha256 = text => createHash('sha256').update(text).digest('base64');
class User {
constructor(email = '', password = '') {
@ -33,4 +33,4 @@ class User {
}
}
module.exports = User;
export default User;

View File

@ -1,28 +1,28 @@
const Constants = require('../data_providers/constants');
const Utils = require('../utils/utils');
const DebugInfo = require('./DebugInfo');
import Constants from '../data_providers/constants.js';
import Utils from '../utils/utils.js';
import DebugInfo from './DebugInfo.js';
class Vehicle {
brand
model
color
year
category
engine
number
currentNumber
vin1
vin2
sts
pts
isRightWheel
isJapanese
photos
addedDate
addedBy
ownershipPeriods
events
notes
brand;
model;
color;
year;
category;
engine;
number;
currentNumber;
vin1;
vin2;
sts;
pts;
isRightWheel;
isJapanese;
photos;
addedDate;
addedBy;
ownershipPeriods;
events;
notes;
static fromAvtocod(report) {
//console.log(JSON.stringify(report));
@ -197,4 +197,4 @@ class Vehicle {
}
}
module.exports = Vehicle;
export default Vehicle;

209
package-lock.json generated
View File

@ -10,7 +10,6 @@
"license": "MIT",
"dependencies": {
"abort-controller": "^3.0.0",
"body-parser": "^1.19.0",
"centrifuge": "^3.1.0",
"compress": "^0.99.0",
"compression": "^1.7.4",
@ -21,8 +20,10 @@
"express-bearer-token": "^2.4.0",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.3.0",
"node-html-parser": "^2.0.0",
"node-html-parser": "^6.0.0",
"prebuilt-tdlib": "^0.1008026.0",
"response-time": "^2.3.2",
"tdl": "^7.4.1",
"utf8": "^3.0.0",
"uuid": "^8.3.0",
"ws": "^8.12.0"
@ -405,28 +406,10 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"node_modules/brace-expansion": {
"version": "1.1.11",
@ -673,6 +656,32 @@
"node": ">= 8"
}
},
"node_modules/css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -732,6 +741,57 @@
"node": ">=6.0.0"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dotenv": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
@ -766,6 +826,17 @@
"node": ">= 0.8"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
@ -983,6 +1054,11 @@
"node": ">=6"
}
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@ -1802,14 +1878,41 @@
"node": ">= 0.6"
}
},
"node_modules/node-addon-api": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
},
"node_modules/node-gyp-build": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
"integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/node-html-parser": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-2.2.1.tgz",
"integrity": "sha512-Vccqb62t6t7DkMVwqPQgb0NWO+gUMMDm+1X3LzqbtXLqjilCTtUYTlniKk08yuA1zIhEFVzu/dozpqs5KZbRFQ==",
"version": "6.1.12",
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.12.tgz",
"integrity": "sha512-/bT/Ncmv+fbMGX96XG9g05vFt43m/+SYKIs9oAemQVYyVcZmDAI2Xq/SbNcpOA35eF0Zk2av3Ksf+Xk8Vt8abA==",
"dependencies": {
"css-select": "^5.1.0",
"he": "1.2.0"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -1953,6 +2056,11 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
"node_modules/prebuilt-tdlib": {
"version": "0.1008026.0",
"resolved": "https://registry.npmjs.org/prebuilt-tdlib/-/prebuilt-tdlib-0.1008026.0.tgz",
"integrity": "sha512-LLlaWPgvTttArop9FnFbjZ+fi5+s7TNiEyil7bTXAdgSBpNvzT1eboNA2Qcej6B9fglPewhtjyu8m91jky564Q=="
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -2049,20 +2157,6 @@
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@ -2317,6 +2411,39 @@
"node": ">=8"
}
},
"node_modules/tdl": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/tdl/-/tdl-7.4.1.tgz",
"integrity": "sha512-7EkVpgAndBAd+jMeRR+FI3v/Y0iy0bmcTDNACqp9Dtg+4AWdLb7fdjbMCEOuL2+ezjoslInXKx9SNWJ1vBT11A==",
"hasInstallScript": true,
"dependencies": {
"debug": "^4.3.4",
"eventemitter3": "^4.0.7",
"node-addon-api": "^6.0.0",
"node-gyp-build": "^4.6.0"
}
},
"node_modules/tdl/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/tdl/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",

View File

@ -3,16 +3,16 @@
"version": "1.0.0",
"description": "AutoCat app backend",
"main": "index.js",
"type": "module",
"scripts": {
"server": "node --async-stack-traces --trace-warnings index.js",
"migration": "node --async-stack-traces --trace-warnings migration.js",
"server": "node --js-promise-withresolvers --async-stack-traces --trace-warnings index.js",
"migration": "node --js-promise-withresolvers --async-stack-traces --trace-warnings migration.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Selim Mustafaev",
"license": "MIT",
"dependencies": {
"abort-controller": "^3.0.0",
"body-parser": "^1.19.0",
"centrifuge": "^3.1.0",
"compress": "^0.99.0",
"compression": "^1.7.4",
@ -23,8 +23,10 @@
"express-bearer-token": "^2.4.0",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.3.0",
"node-html-parser": "^2.0.0",
"node-html-parser": "^6.0.0",
"prebuilt-tdlib": "^0.1008026.0",
"response-time": "^2.3.2",
"tdl": "^7.4.1",
"utf8": "^3.0.0",
"uuid": "^8.3.0",
"ws": "^8.12.0"

View File

@ -1,7 +1,7 @@
const express = require('express');
const router = express.Router();
const { v4: uuidv4 } = require('uuid');
const Utils = require('../utils/utils');
import { Router } from 'express';
const router = Router();
import { v4 as uuidv4 } from 'uuid';
import Utils from '../utils/utils.js';
const makeError = error => ({ success: false, error });
@ -99,4 +99,4 @@ router.get('/', async (req, res) => {
}
});
module.exports = router;
export default router;

View File

@ -1,6 +1,6 @@
const express = require('express');
const router = express.Router();
const { makeError } = require('../utils/errors');
import { Router } from 'express';
const router = Router();
import { makeError } from '../utils/errors.js';
router.post('/', async (req, res) => {
const { number, notes } = req.body;
@ -67,4 +67,4 @@ router.delete('/', async (req, res) => {
}
});
module.exports = router;
export default router;

View File

@ -1,8 +1,9 @@
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const User = require('../models/user');
const { errorCodes, makeError } = require('../utils/errors');
import { Router } from 'express';
import Jwt from 'jsonwebtoken';
import User from '../models/user.js';
import { errorCodes, makeError } from '../utils/errors.js';
const router = Router();
router.post('/signup', async (req, res) => {
const { email, password } = req.body;
@ -13,7 +14,7 @@ router.post('/signup', async (req, res) => {
if(users.length == 0) {
let user = new User(email, password);
await collection.insertOne(user.toDB());
user.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
user.token = Jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
res.send({ success: true, data: user });
} else {
res.send(makeError('User already exists'));
@ -40,7 +41,7 @@ router.post('/login', async (req, res) => {
return;
}
me.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
me.token = Jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
res.send({ success: true, data: me });
} else {
res.send(makeError('Incorrect login or password', errorCodes.invalidLoginOrPassword));
@ -67,12 +68,12 @@ router.post('/signIn', async (req, res) => {
return;
}
me.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
me.token = Jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
res.send({ success: true, data: me });
} else {
let user = new User(email, password);
await users.insertOne(user.toDB());
user.token = jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
user.token = Jwt.sign({ email }, process.env.JWT_SECRET_AUTH, { expiresIn: process.env.JWT_EXPIRATION_TIME });
res.send({ success: true, data: user });
}
} catch(ex) {
@ -106,4 +107,4 @@ router.get('/find', async (req, res) => {
res.status(code).send({ success: true, data: { users } });
});
module.exports = router;
export default router;

View File

@ -1,16 +1,18 @@
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const cors = require('cors');
const AvtocodProvider = require('../data_providers/avtocod');
const Vin01Provider = require('../data_providers/vin01');
const { regions } = require('../data_providers/constants');
const RsaProvider = require('../data_providers/rsa');
const NomerogramProvider = require('../data_providers/nomerogram');
const Utils = require('../utils/utils');
const ObjectId = require('mongodb').ObjectId;
const DebugInfo = require('../models/DebugInfo');
const Vehicle = require('../models/vehicle');
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 });
@ -231,7 +233,7 @@ router.get('/colors', async (req, res) => {
});
router.get('/regions', (req, res) => {
res.send({ success: true, data: regions });
res.send({ success: true, data: Constants.regions });
});
router.get('/years', async (req, res) => {
@ -247,7 +249,7 @@ router.get('/years', async (req, res) => {
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 { 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) {
@ -282,4 +284,43 @@ router.post('/checkOsago', async (req, res) => {
}
});
module.exports = router;
router.post('/checkGbTg', async (req, res) => {
try {
const number = req.body.number.replace(/ /g, '').toUpperCase();
let tgProvider = new TGProvider();
await tgProvider.init();
let report = await tgProvider.getReport(number);
await tgProvider.close();
let collection = req.db.collection('vehicles');
let vehicle = await collection.findOne({ number });
if(vehicle) {
let vinRegex = RegExp(vehicle.vin1.replace(/\*/g, '.'));
//let stsRegex = RegExp(vehicle.sts.replace(/\*/g, '.'));
if(report.vin.match(vinRegex) /*&& report.sts.match(stsRegex)*/) {
let updatedFields = {
vin1: report.vin,
color: report.color,
sts: report.sts,
updatedDate: Date.now()
}
await collection.updateOne({ number }, { $set: updatedFields });
res.send({ success: true, data: Object.assign(vehicle, updatedFields) });
} else {
res.send(makeError('Vehicle doesn\'t match'));
}
} else {
res.send(makeError('Vehicle not found'));
}
} catch(ex) {
res.send(makeError(ex.message));
console.error(ex);
}
});
export default router;

View File

@ -27,4 +27,4 @@ const makeError = (error, code) => {
return result;
};
module.exports = { errorCodes, makeError };
export { errorCodes, makeError };

View File

@ -135,4 +135,4 @@ class Utils {
}
}
module.exports = Utils;
export default Utils;