136 lines
3.8 KiB
JavaScript
136 lines
3.8 KiB
JavaScript
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);
|
|
}
|
|
});
|
|
}
|
|
|
|
} |