initial commit
This commit is contained in:
136
server/ImhdClient.js
Normal file
136
server/ImhdClient.js
Normal file
@@ -0,0 +1,136 @@
|
||||
import * as fs from 'fs';
|
||||
import path from "path";
|
||||
import https from 'https';
|
||||
import {fileURLToPath} from "url";
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
const imhdData = path.dirname(path.dirname(fileURLToPath(import.meta.url))) + '/dist/imhd';
|
||||
|
||||
export default class ImhdClient {
|
||||
|
||||
constructor() {
|
||||
fs.mkdirSync(imhdData + '/icons', { recursive: true });
|
||||
|
||||
this.cache = {};
|
||||
this.loadCache();
|
||||
}
|
||||
|
||||
getVehicleData(vehicleId) {
|
||||
if (this.cache.hasOwnProperty(vehicleId)) {
|
||||
return this.cache[vehicleId];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async search(phrase) {
|
||||
let resp = await fetch('https://imhd.sk/ba/api/sk/vyhladavanie?q=' + encodeURIComponent(phrase));
|
||||
if (!resp.ok) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return resp.json();
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async downloadVehicleIcon(vehicleId) {
|
||||
if (this.cache.hasOwnProperty(vehicleId)) {
|
||||
if (this.cache[vehicleId].type)
|
||||
return this.cache[vehicleId].url;
|
||||
}
|
||||
|
||||
const randId = nanoid(5);
|
||||
const iconPath = imhdData + '/icons/' + randId + '.png';
|
||||
if (fs.existsSync(iconPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let results = await this.search(vehicleId);
|
||||
if (!results) {
|
||||
console.log('Search for vehicle unsuccessful:', vehicleId);
|
||||
return null;
|
||||
}
|
||||
results = results.results || [];
|
||||
|
||||
for (let obj of results) {
|
||||
if ((typeof obj.img) !== 'string' || obj.img.length < 10)
|
||||
continue;
|
||||
|
||||
const urlParts = obj.url.trim().split('/');
|
||||
if (urlParts.length < 3)
|
||||
continue;
|
||||
|
||||
if (urlParts[2] !== 'vozidlo')
|
||||
continue;
|
||||
|
||||
if (!obj.name.endsWith('#' + vehicleId))
|
||||
continue;
|
||||
|
||||
let matches = obj.img.match(/.*src="([^"]*)".*/);
|
||||
if (!matches)
|
||||
continue;
|
||||
|
||||
const url = 'https://imhd.sk' + matches[1];
|
||||
const existing = Object.values(this.cache).find(el => el.url === url);
|
||||
if (!existing) {
|
||||
// TODO: Path traversal vulnerability here!
|
||||
await this.downloadFile(url, iconPath);
|
||||
fs.appendFile(
|
||||
imhdData + '/names.txt',
|
||||
vehicleId + '|' + obj.name + "\n",
|
||||
err => { err && console.error(err); }
|
||||
);
|
||||
}
|
||||
|
||||
this.cache[vehicleId] = {
|
||||
img: existing ? existing.img : randId,
|
||||
url: url,
|
||||
type: obj.class,
|
||||
info: obj.url,
|
||||
};
|
||||
this.saveCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async downloadFile(url, target) {
|
||||
return new Promise ((resolve, reject) => {
|
||||
const file = fs.createWriteStream(target);
|
||||
https.get(url, resp => {
|
||||
resp.pipe(file);
|
||||
|
||||
file.on('finish', () => {
|
||||
file.close();
|
||||
console.log('Downloaded', url);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadCache() {
|
||||
try {
|
||||
let cacheFile = fs.readFileSync(imhdData + '/iconsdb.json');
|
||||
if (cacheFile) {
|
||||
let parsed = JSON.parse(cacheFile);
|
||||
if (parsed) {
|
||||
this.cache = parsed;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Cannot read iconsdb.json for ImhdClient', e);
|
||||
}
|
||||
}
|
||||
|
||||
saveCache() {
|
||||
fs.writeFile(imhdData + '/iconsdb.json', JSON.stringify(this.cache, null, 2), err => {
|
||||
if (err) {
|
||||
console.log('Cannot save cache for ImhdClient', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user