You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
6.5 KiB
JavaScript

const superagent = require('superagent');
const LotListing = require('./LotListing')
const brickLinkAgent = superagent.agent().set('Accept', 'application/json');
const htmlParser = require('node-html-parser');
const _ = require('lodash');
const brickOwlKey = process.env.brickowlKey
module.exports = {
getInternalPartId(legoPartNumber, type = 'Part') {
return new Promise((resolve, reject) => {
brickLinkAgent.get(`https://api.brickowl.com/v1/catalog/id_lookup`)
.query({
key: brickOwlKey,
id: legoPartNumber,
type: type,
})
// .set('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:107.0) Gecko/20100101 Firefox/107.0')
.then((response => {
if(response.statusCode !== 200) throw response.statusCode;
const possibleIds = _.get(response, 'body.boids');
if(possibleIds.length != 1) {
throw new Error(`Unable to uniquely get internal id for part ${legoPartNumber}, found ${possibleIds}`)
}
return resolve(possibleIds[0]);
})).catch(error => {
reject(error);
})
})
},
getListings(internalPartId, colorId) {
return new Promise(async (resolve, reject) => {
await new Promise((resolve) => setTimeout(resolve, Math.random() * 500 + 100));
var query = {
key: brickOwlKey,
boid: internalPartId,
country: 'US'
// loc: 'US',
// rpp: 100
// cond: 'U'
}
if(colorId){
query.color = colorId
}
brickLinkAgent.get(`https://api.brickowl.com/v1/catalog/availability`)
.query(query)
// .set('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:107.0) Gecko/20100101 Firefox/107.0')
.set('Accept', 'application/json').then(response => {
if(!response.body) {
console.log(response.body, query)
return reject('no list found');
}
//convert to array
const list = _.values(response.body).filter(lot => {
return lot.country === 'US' && lot.base_currency === 'USD'
});
resolve(list.map(l => new LotListing({
idInv: l.lot_id,
strDesc: l.url,
codeNew: l.con === 'new' ? 'N' : 'U',
codeComplete: null,
n4Qty: parseInt(l.qty),
strColor: 'UHHHH',
idColor: l.boid.includes('-') ? l.boid.substring(l.boid.indexOf('-') + 1) : 0,
mMinBuy: l.minimum_order,
strSellerUsername: l.store_id,
strStorename: l.store_name,
instantCheckout: false,
legoPartNumber: 'UHHHH',
boid: l.boid,
mDisplaySalePrice: l.price
})));
}).catch(error => {
console.error('HTTP error from getListings', error)
reject(error);
})
})
},
getListingsByLegoPartNumber(legoPartNumber, colorId){
return module.exports.getInternalPartId(legoPartNumber).then((blPartNumber) => module.exports.getListings(blPartNumber, colorId)).then(listings => {
return listings.map(listing => {
listing.legoPartNumber = legoPartNumber
return listing;
})
})
},
getStoreId(sellerUsername) {
return new Error('Not implemented');
return new Promise((resolve, reject) => {
brickLinkAgent.get(`https://store.bricklink.com/${sellerUsername}`)
.then((response => {
const storeIdRegex = /username:\s+'.+',\s+id:\s+(?<storeId>\d+)/gm;
const matches = storeIdRegex.exec(response.text);
resolve(matches.groups?.storeId)
})).catch(error => {
console.error('HTTP error from getStoreId', error)
reject(error);
})
})
},
getSetInventory(setId) {
return new Promise(async (resolve, reject) => {
const setBoid = await module.exports.getInternalPartId(setId, 'Set')
brickLinkAgent.get(`https://api.brickowl.com/v1/catalog/inventory`)
.query({
key: brickOwlKey,
boid: setBoid
})
.then((response => {
return resolve(_.get(response, 'body.inventory', []).map(type => {
return {
partNumber: null,
internalPartId: type.boid,
colorId: null,
quantity: type.quantity
}
}))
// var root = htmlParser.parse(response.text);
// const rows = root.querySelectorAll('.IV_ITEM')
// const parsed = rows.map(row => {
// const partRegex = /\/v2\/catalog\/catalogitem.page\?P=(?<legoPartNumber>.+)&idColor=(?<colorId>\d+)/gm;
// const quantityRegex = /<TD ALIGN="RIGHT">\&nbsp;(?<quantity>\d+)/gm
// const matches = partRegex.exec(row.innerHTML);
// const quantityMatches = quantityRegex.exec(row.innerHTML);
// if(!matches) return null;
// return {
// partNumber: matches.groups?.legoPartNumber,
// colorId: parseInt(matches.groups?.colorId),
// quantity: parseInt(quantityMatches.groups?.quantity)
// }
// }).filter(r => r !== null);
resolve(parsed)
})).catch(error => {
console.error('HTTP error from getStoreId', error)
reject(error);
})
})
},
getDetails(boid) {
return new Promise((resolve, reject) => {
brickLinkAgent.get(`https://api.brickowl.com/v1/catalog/lookup`)
.query({
key: brickOwlKey,
boid: boid
})
.then((response => {
resolve(response.body)
})).catch(error => {
console.error('HTTP error from getStoreId', error)
reject(error);
})
})
}
}