Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 34eef28

Browse files
committed
Added Jeep (factory site), which is kind of worthless.
1 parent 9b32037 commit 34eef28

6 files changed

Lines changed: 474 additions & 28 deletions

File tree

65.2 KB
Binary file not shown.
109 KB
Binary file not shown.

jeep-mfg.js

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
const fetch = require('node-fetch');
2+
const moment = require('moment');
3+
const fs = require('fs');
4+
5+
const radiusMiles = 150;
6+
7+
function formatCurrency(numberString) {
8+
let result = ''
9+
for (let i = numberString.length - 1; i > -1; i--) {
10+
result = numberString.charAt(i) + result;
11+
const pos = numberString.length - i;
12+
if (pos > 0 && pos % 3 === 0) result = ',' + result;
13+
}
14+
return '$' + result;
15+
}
16+
17+
function makeImageUrl(urlParams, width, interior=false) {
18+
const imageUrl = 'https://www.jeep.com/mediaserver/iris?'
19+
let pov = 'fullfronthero';
20+
let height = Math.trunc(width / 6 * 4);
21+
if (interior) {
22+
pov = 'I01';
23+
height = Math.trunc(width / 6 * 8);
24+
}
25+
const renderSettings = `&pov=${pov}&width=${width}&height=${height}&bkgnd=white&resp=jpg`;
26+
return `${imageUrl}${urlParams}${renderSettings}`;
27+
}
28+
29+
async function getDealers(zipCode) {
30+
const url = 'https://www.jeep.com/bdlws/MDLSDealerLocator?zipCode=ZIPCODE&func=SALES&radius=RADIUSMILES&brandCode=J&resultsPerPage=999'
31+
const requestUrl = url
32+
.replace('ZIPCODE', zipCode)
33+
.replace('RADIUSMILES', radiusMiles);
34+
const response = await fetch(requestUrl);
35+
const data = await response.json();
36+
const result = data.status;
37+
if (!result === 200) {
38+
console.error(`Could not get dealer list for ${zipCode}: ${result}`);
39+
return [];
40+
}
41+
const dealers = [];
42+
for (const dealer of data.dealer) {
43+
let dealerAddress = dealer.dealerAddress1;
44+
if (dealer.dealerAddress2) dealerAddress += dealer.dealerAddress2;
45+
dealers.push({
46+
code: dealer.dealerCode,
47+
name: dealer.dealerName,
48+
address: `${dealerAddress}, ${dealer.dealerCity}, ${dealer.dealerState}`,
49+
cityState: `${dealer.dealerCity}, ${dealer.dealerState}`
50+
})
51+
}
52+
53+
console.log(`Obtained ${dealers.length} dealers for ${zipCode}`);
54+
return dealers;
55+
}
56+
57+
function isCarValid(car, filters) {
58+
if (filters.engineCodes) {
59+
if (filters.engineCodes.indexOf(car.engineCode) === -1) return false;
60+
}
61+
62+
if (filters.transmissionCodes) {
63+
if (filters.transmissionCodes.indexOf(car.transmissionCode) === -1) return false;
64+
}
65+
66+
if (filters.exteriorColorCodes) {
67+
if (filters.exteriorColorCodes.indexOf(car.exteriorColorCode) === -1) return false;
68+
}
69+
70+
if (filters.options) {
71+
for (const option of filters.options) {
72+
if (Array.isArray(option)) {
73+
let match = false;
74+
for (const optionCode of option) {
75+
if (car.options.indexOf(optionCode) > -1) {
76+
match = true;
77+
break;
78+
}
79+
}
80+
if (!match) return false;
81+
} else {
82+
if (car.options.indexOf(option) === -1) return false;
83+
}
84+
}
85+
}
86+
87+
return true;
88+
}
89+
90+
async function getCars(filters, zipCode, dealers) {
91+
const url = 'https://www.jeep.com/hostd/inventory/getinventoryresults.json?func=SALES&includeIncentives=Y&matchType=X&modelYearCode=IUJ202010&pageNumber=PAGENUMBER&pageSize=PAGESIZE&radius=RADIUSMILES&sortBy=0&zip=ZIPCODE'
92+
const pageSize = 10000;
93+
const requestUrl = url
94+
.replace('PAGENUMBER', 1)
95+
.replace('ZIPCODE', zipCode)
96+
.replace('RADIUSMILES', radiusMiles)
97+
.replace('PAGESIZE', pageSize);
98+
// console.log(requestUrl);
99+
const response = await fetch(requestUrl);
100+
const data = await response.json();
101+
const result = data.result.result
102+
if (!result === "SUCCESS") {
103+
console.error(`${result}: ${data.result.errors.join(', ')}`);
104+
return [];
105+
}
106+
const cars = data.result.data.vehicles;
107+
console.log(`${cars.length} cars found.`);
108+
if (cars.length === pageSize) {
109+
console.warning('There may be more cars available; send another request!');
110+
}
111+
if (cars.length < data.result.data.metadata.totalCount) {
112+
console.warning('There are more cars available; send another request!');
113+
}
114+
filteredCars = []
115+
for (const car of cars) {
116+
if (filters && !isCarValid(car, filters)) continue;
117+
118+
if (car.incentives) {
119+
console.log(car.incentives);
120+
}
121+
122+
const engine = car.engineDesc;
123+
const tranny = car.transmissionDesc;
124+
const model = car.vehicleDesc;
125+
const vin = car.vin;
126+
const interior = car.interiorFabric;
127+
const employeePrice = car.price.employeePrice;
128+
const totalPrice = car.price.netPrice;
129+
const options = car.options;
130+
let doors;
131+
for (const attribute of car.attributes.attributes) {
132+
if (attribute.typeDesc === "Doors") {
133+
doors = attribute.value;
134+
}
135+
}
136+
const exteriorImageUrl = makeImageUrl(car.extImage, 1000, false);
137+
const interiorImageUrl = makeImageUrl(car.intImage, 1000, true);
138+
const modelYearCode = car.ccode.substring(0, 9);
139+
const windowSticker = `https://www.jeep.com/hostd/windowsticker/getWindowStickerPdf.do?vin=${vin}`
140+
let dealer = dealers.filter(a => a.code === car.dealerCode);
141+
if (dealer.length !== 1) {
142+
console.error(`${dealer.length} dealers found for car with dealer code = ${car.dealerCode}`);
143+
}
144+
dealer = dealer[0];
145+
// mine: https://www.jeep.com/new-inventory/vehicle-details.html?modelYearCode=IUJ202010&vin=1C4HJXFN2LW266150&dealerCode=60385&radius=150&matchType=X&statusCode=KZX&ref=details&variation=undefined
146+
// theirs: https://www.jeep.com/new-inventory/vehicle-details.html?modelYearCode=IUJ202010&vin=1C4HJXCG0LW205403&dealerCode=26852&radius=150&matchType=X&statusCode=KZX&ref=details&variation=undefined
147+
// My generated URLs don't load properly.
148+
const carUrl = `https://www.jeep.com/new-inventory/vehicle-details.html?modelYearCode=${modelYearCode}&vin=${vin}&dealerCode=${dealer.code}&radius=${radiusMiles}&matchType=X&statusCode=${car.statusCode}&ref=details&variation=undefined`
149+
thisCar = {
150+
model, engine, tranny, vin, interior, employeePrice, totalPrice,
151+
options, doors, exteriorImageUrl, interiorImageUrl,
152+
windowSticker,
153+
url: carUrl,
154+
finalPrice: employeePrice ? formatCurrency(employeePrice) : formatCurrency(totalPrice),
155+
msrp: formatCurrency(totalPrice),
156+
rawData: car,
157+
dealer: dealer
158+
};
159+
filteredCars.push(thisCar);
160+
}
161+
162+
console.log(`Obtained ${filteredCars.length} cars from a total of ${cars.length} for ${zipCode}`);
163+
return filteredCars;
164+
}
165+
166+
async function run() {
167+
const zipCodes = [
168+
77478,
169+
94610
170+
]
171+
172+
let promises = [];
173+
for (const zipCode of zipCodes) {
174+
promises.push(getDealers(zipCode));
175+
}
176+
177+
const dealersByZip = await Promise.all(promises);
178+
const allDealers = [];
179+
for (const dealers of dealersByZip) {
180+
allDealers.push(...dealers);
181+
}
182+
183+
const filter = {
184+
transmissionCodes: ['DFT'],
185+
options: [
186+
['HT1', 'HT3'], // hard top
187+
'ADE', // heated seats
188+
'ALP', // adaptive cruise
189+
['AAN', 'AEK'], // CarPlay
190+
// 'AJ1', // ParkSense
191+
],
192+
exteriorColorCodes: ['PRC', 'PDN', 'PBM', 'PYV', 'PGG']
193+
}
194+
195+
promises = [];
196+
for (const zipCode of zipCodes) {
197+
promises.push(getCars(filter, zipCode, allDealers));
198+
}
199+
200+
const carsByZip = await Promise.all(promises);
201+
const allCars = [];
202+
for (const cars of carsByZip) {
203+
allCars.push(...cars);
204+
}
205+
206+
allCars.sort(function (a, b) {
207+
if (a.finalPrice < b.finalPrice) return -1;
208+
if (a.finalPrice > b.finalPrice) return 1;
209+
return 0;
210+
});
211+
212+
const archive = `archive/jeep_${moment().format('YYYY-MM-DD_HH-mm-ss')}.json`;
213+
fs.writeFileSync(archive, JSON.stringify(allCars, null, 2), err => {
214+
console.error(err);
215+
});
216+
217+
fs.writeFileSync('jeep.json', JSON.stringify(allCars, null, 2), err => {
218+
console.error(err);
219+
});
220+
221+
return allCars;
222+
}
223+
224+
module.exports = {run};

jeep_codes.js

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
const codes = [
2+
{
3+
code: 'DFV',
4+
description: '8-speed automatic (ZF 8HP75 - diesel only)'
5+
},
6+
{
7+
code: 'DFT',
8+
description: '8-speed automatic (ZF 850RE - gasoline only)'
9+
},
10+
{
11+
code: 'ERG',
12+
description: '3.6L V6 24V VVT eTorque'
13+
},
14+
{
15+
code: 'ERC',
16+
description: '3.6L V6 24V VVT ESS'
17+
},
18+
{
19+
code: 'EXJ',
20+
description: '3.0L V6 Turbo Diesel Engine ESS'
21+
},
22+
{
23+
code: 'EC3',
24+
description: '2.0L I4 DOHC DI Turbo eTorque'
25+
},
26+
{
27+
code: 'EC1',
28+
description: '2.0L I4 DOHC DI Turbo ESS'
29+
},
30+
// These are part of the "quick order" packages, which is how
31+
// trims are differentiated. E.g. Wrangler Sport has none of these.
32+
{
33+
code: 'HAA',
34+
description: 'Air conditioning'
35+
},
36+
{
37+
code: 'GCD',
38+
description: 'Deep tint sunscreen windows'
39+
},
40+
{
41+
code: 'GTB',
42+
description: 'Power heated mirrors'
43+
},
44+
{
45+
code: 'JPY',
46+
description: 'Power windows'
47+
},
48+
{
49+
code: 'GXM',
50+
description: 'Remote keyless entry'
51+
},
52+
53+
// individual options
54+
{
55+
code: 'HT1',
56+
description: 'Black hard-top',
57+
dealerCost: 1166
58+
},
59+
{
60+
code: 'HT3',
61+
description: 'Body color hard-top',
62+
dealerCost: 1080 // depends on model
63+
},
64+
{
65+
code: 'CMD',
66+
description: 'Cargo group with trail rail system',
67+
dealerCost: 176
68+
},
69+
{
70+
code: 'ADE',
71+
description: 'Cold weather group (heated seats)',
72+
dealerCost: 896 // 626 with manual tranny
73+
},
74+
{
75+
code: 'AJ1',
76+
description: 'Safety group (ParkSense)', // maybe not needed with rear camera?
77+
dealerCost: 896
78+
},
79+
{
80+
code: 'AAN',
81+
description: 'Technology group (Apple CarPlay)',
82+
dealerCost: 896
83+
},
84+
{
85+
code: 'AEK',
86+
description: 'Premium audio (Apple CarPlay)',
87+
dealerCost: 1661
88+
},
89+
{
90+
code: 'ALP',
91+
description: 'Advanced safety group (adaptive cruise control)',
92+
dealerCost: 716
93+
},
94+
95+
// Interior fabric
96+
{
97+
code: 'A7',
98+
description: 'Cloth seats',
99+
dealerCost: 0
100+
},
101+
{
102+
code: 'X9',
103+
description: 'Black',
104+
dealerCost: 0
105+
},
106+
{
107+
code: 'T5',
108+
description: 'Black and tan',
109+
dealerCost: 0
110+
},
111+
// Colors
112+
{
113+
code: 'PRC',
114+
description: 'Firecracker red',
115+
dealerCost: 0
116+
},
117+
{
118+
code: 'PDN',
119+
description: 'Sting-gray',
120+
dealerCost: 0
121+
},
122+
{
123+
code: 'PBM',
124+
description: 'Ocean blue metallic',
125+
dealerCost: 221
126+
},
127+
{
128+
code: 'PYV',
129+
description: 'Hellayella',
130+
dealerCost: 0
131+
},
132+
{
133+
code: 'PGG',
134+
description: 'Sarge green',
135+
dealerCost: 0
136+
},
137+
// Individual codes for features I really want
138+
{
139+
code: 'RFP',
140+
description: 'Apple CarPlay',
141+
},
142+
{
143+
code: 'JPM',
144+
description: 'Heated front seats',
145+
},
146+
{
147+
code: 'XAA',
148+
description: 'Parksense rear',
149+
},
150+
{
151+
code: 'NH3', // code is NH1 with manual tranny because that one won't stop on its own.
152+
description: 'Adaptive cruise',
153+
},
154+
{
155+
code: 'GFA', // Part of 3 piece hard top
156+
description: 'Rear window defroster',
157+
},
158+
];

0 commit comments

Comments
 (0)