Last active
October 16, 2019 03:43
-
-
Save lifehome/a7e19d776edecaf685c0f7d39b633672 to your computer and use it in GitHub Desktop.
Jumbo API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'), | |
maths = require('mathjs'), | |
restify = require('restify'), | |
rp = require('request-promise'), | |
cheerio = require('cheerio'), | |
cheerioTableparser = require('cheerio-tableparser') | |
server = restify.createServer({ | |
name: 'wrench-jumbo', | |
version: '1.0.1' | |
}), | |
server_socket = '/opt/httpd/it/hkno/apiserv.sock', | |
clist = require(__dirname + '/libs/categories.js') | |
server.use(restify.plugins.gzipResponse()); | |
server.use(restify.plugins.acceptParser(["application/json"])) | |
// Promise: Get product JSON object | |
let getProductJSON = (cid = 3) => { | |
// Fetch and return JSON Object | |
return rp(`http://www.jumbo-computer.com/pricelist.aspx?id=${cid}&sort=1`).then(res=>{ | |
if (res.match(/"gvProducts"/g) == null) return JSON.parse('{"error": "No data."}') | |
let $ = cheerio.load(res) | |
cheerioTableparser($) | |
let rawdata = $('table.gvProducts').parsetable(true, true, true) | |
// Remove garbages | |
delete rawdata[2] | |
// Process garbage | |
let pricing = rawdata[1].map(e=>{ | |
return parseInt(e.replace('HK\$ ', '')) | |
}).sort() | |
// Construct statistic object | |
let stats = { | |
'min': maths.min(pricing), | |
'max': maths.max(pricing), | |
'mean': maths.round(maths.mean(pricing), 3), | |
'median': maths.median(pricing), | |
'std': maths.round(maths.std(pricing), 3) | |
} | |
// Return processed JSON object | |
let product = rawdata[0].reduce((arr, name, idx)=>{ | |
arr.push({ name, price: pricing[idx] }) | |
return arr | |
}, []) | |
return { | |
'merchants': product, | |
'statistic': stats | |
} | |
}).catch(e=>{ | |
return JSON.parse(`{"error": ${e}}`) | |
}) | |
} | |
// Promise: Search for product JSON object | |
let searchProduct = (cid, keyword) => { | |
// Fetch and return JSON object | |
return rp(`http://www.jumbo-computer.com/pricelist.aspx?id=${cid}&desc=${keyword}&sort=1`).then(res=>{ | |
if (res.match(/"gvProducts"/g) == null) return JSON.parse('{"error": "No data."}') | |
let $ = cheerio.load(res) | |
cheerioTableparser($) | |
let rawdata = $('table.gvProducts').parsetable(true, true, true) | |
// Remove garbages | |
delete rawdata[2] | |
// Process garbage | |
let pricing = rawdata[1].map(e=>{ | |
return parseInt(e.replace('HK\$ ', '')) | |
}).sort() | |
// Construct statistic object | |
let stats = { | |
'min': maths.min(pricing), | |
'max': maths.max(pricing), | |
'mean': maths.round(maths.mean(pricing), 3), | |
'median': maths.median(pricing), | |
'std': maths.round(maths.std(pricing), 3) | |
} | |
// Return processed JSON object | |
let product = rawdata[0].reduce((arr, name, idx)=>{ | |
arr.push({ name, price: pricing[idx] }) | |
return arr | |
}, []) | |
return { | |
'merchants': product, | |
'statistic': stats | |
} | |
}).catch(e=>{ | |
return JSON.parse(`{"error": ${e}}`) | |
}) | |
} | |
// GET request: Return price listing from Jumbo per category | |
let listingGETHandler = (req, res, next)=>{ | |
if(Number(req.params.cid) && Number(req.params.cid) >= 1 && Number(req.params.cid) <= 136){ | |
res.cache('public') | |
getProductJSON(req.params.cid).then(result => { | |
res.charSet('utf-8') | |
res.json(result) | |
}) | |
} else res.json({"error": "Incorrect category ID.", "reference": "/jumbo/categories"}) | |
} | |
// GET request: Return price listing from Jumbo per search query | |
let searchGETHandler = (req, res, next)=>{ | |
res.cache('public') | |
searchProduct(req.params.cid, req.params.keyword).then(result =>{ | |
res.charSet('utf-8') | |
res.json(result) | |
}) | |
} | |
let emptylistingGETHandler = (req, res, next)=>{ | |
res.json(JSON.parse('{"error": "Please input the category number followed by the endpoint.", "reference": "/jumbo/categories"}')) | |
} | |
let categoriesGETHandler = (req, res, next)=>{ | |
res.charSet('utf-8') | |
res.json(clist.category) | |
} | |
server.get('/jumbo/categories', categoriesGETHandler) | |
server.get('/jumbo/search/:cid/:keyword', searchGETHandler) | |
server.get('/jumbo/listing', emptylistingGETHandler) | |
server.get('/jumbo/listing/:cid', listingGETHandler) | |
server.get('/ios/beta.mobileconfig', restify.plugins.serveStatic({ | |
directory: './static', | |
file: 'ios11beta.mobileconfig' | |
}) | |
) | |
fs.existsSync(server_socket) && fs.unlinkSync(server_socket) | |
server.listen(server_socket, ()=>{ | |
fs.chmodSync(server_socket, '777'); | |
console.log(`[*] Booting up at ${new Date()}\n[+] API server is now up, listening at: https://api.hkno.it`); | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment