trippe
Advanced tools
Comparing version 0.3.0 to 0.4.0
45
index.js
@@ -40,3 +40,5 @@ import got from 'got' | ||
// Set headers | ||
const { version } = readPackageSync() | ||
const { version } = readPackageSync({ | ||
cwd: new URL('./', import.meta.url) | ||
}) | ||
@@ -130,3 +132,4 @@ this.#headers = { | ||
/** | ||
* Returns an array of lowest prices (in points and in cash) for a single hotel - per night and for a period of up to 62 days | ||
* Returns an object with the hotelCode, the currencyCode and an array of lowest prices (in points and in cash) for a | ||
* single hotel - per night and for a period of up to 62 days | ||
* Note that the rates that this method returns don't always include (all) taxes | ||
@@ -136,3 +139,3 @@ * | ||
* @param {startEndDates} dates An object containing startDate and endDate keys (both optional) | ||
* @returns {Promise<Array[lowestPriceDay]>} | ||
* @returns {Promise<Object[lowestHotelPrices]>} | ||
*/ | ||
@@ -143,11 +146,16 @@ | ||
* @property {string} startDate The date (check in date) from which to start searching, defaults to today | ||
* @property {string} endDate The last date (as a check in date) to include in the search, defaults to today + 59 days | ||
* @property {string} endDate The last date (as a check in date) to include in the search, defaults to today + 61 days | ||
*/ | ||
/** | ||
* @typedef { Object } lowestHotelPrices | ||
* @property {string} hotelCode The systemwide id (mnemonic) of the hotel | ||
* @property {string} currencyCode The currency used at this hotel | ||
* @property {lowestPriceDay} prices The lowest prices by day | ||
*/ | ||
/** | ||
* @typedef {Object} lowestPriceDay | ||
* @property {string} hotelCode The systemwide id (mnemonic) of the hotel | ||
* @property {string} checkinDate The check in date | ||
* @property {number|null} cashPrice The lowest cash price available - not including (some) taxes for a one night stay, null if no rooms available | ||
* @property {string} currecyCode The cuirrency used for the cashPrice above | ||
* @property {number|null} points The lowest number of points available to book a reward night with points only, null if no reward nights are available | ||
@@ -157,3 +165,3 @@ */ | ||
startDate = dayjs().format('YYYY-MM-DD'), | ||
endDate = dayjs(startDate).add(59, 'day').format('YYYY-MM-DD') | ||
endDate = dayjs(startDate).add(61, 'day').format('YYYY-MM-DD') | ||
} = {}) { | ||
@@ -175,11 +183,17 @@ const headers = this.#headers | ||
const url = `https://apis.ihg.com/availability/v1/windows?hotelCodes=${hotelCode.toUpperCase()}&rateCodes=IVANI,IDMAP,IDME0&startDate=${startDate}T00:00:00Z&endDate=${endDate}T00:00:00Z&lengthOfStay=1&numberOfRooms=1&includeSellStrategy=never` | ||
const dates = [...new Array(days)].map((u, i) => dayjs(startDate).add(i, 'day').format('YYYY-MM-DD')) | ||
const url = `https://apis.ihg.com/availability/v1/windows?hotelCodes=${hotelCode.toUpperCase()}&rateCodes=IVANI,IDMAP,IDME0,IDME2,IGCOR,IDVPD&startDate=${startDate}T00:00:00Z&endDate=${endDate}T00:00:00Z&lengthOfStay=1&numberOfRooms=1&includeSellStrategy=never` | ||
return got.get(url, { headers }).json() | ||
.catch((error) => { | ||
const { statusCode } = error.response | ||
if (statusCode >= 500) { | ||
throw new Error(`API reports a server error (statusCode ${statusCode}). Please retry.`) | ||
} | ||
}) | ||
.then(json => json.hotels[0]) | ||
.then(hotel => { | ||
const { currencyCode, rates } = hotel | ||
const dates = [...new Array(days)].map((u, i) => dayjs(startDate).add(i, 'day').format('YYYY-MM-DD')) | ||
if (rates.length === 0) { | ||
if (currencyCode === '') { | ||
throw new Error('Unknown or invalid hotelCode') | ||
@@ -189,3 +203,3 @@ } else { | ||
return dates.map(checkinDate => { | ||
const prices = dates.map(checkinDate => { | ||
const points = Math.min(...ratesCombined.filter(rate => rate.startDate === `${checkinDate}T00:00:00Z` && 'totalPoints' in rate).map(rate => rate.totalPoints)) | ||
@@ -197,6 +211,11 @@ const cashPrice = Math.min(...ratesCombined.filter(rate => rate.startDate === `${checkinDate}T00:00:00Z` && 'totalAmount' in rate).map(rate => rate.totalAmount)) | ||
cashPrice: cashPrice < Infinity ? cashPrice : null, | ||
currencyCode, | ||
points: points < Infinity ? points : null | ||
} | ||
}) | ||
return { | ||
hotelCode, | ||
currencyCode, | ||
prices | ||
} | ||
} | ||
@@ -218,3 +237,3 @@ }) | ||
* @property {string} startDate The date (check in date) from which to start searching, defaults to today | ||
* @property {string} endDate The last date (as a check in date) to include in the search, defaults to today + 59 days | ||
* @property {string} endDate The last date (as a check in date) to include in the search, defaults to today + 61 days | ||
* @property {number} adults The number of adult guests in the room | ||
@@ -221,0 +240,0 @@ * @property {number} children The number of children in the room |
{ | ||
"name": "trippe", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "Unofficial API client to check hotel prices and reward nights availability - suitable for an intercontinental lifestyle.", | ||
@@ -5,0 +5,0 @@ "license": "GPLV3", |
# Trippe 🏨 | ||
Unofficial API client to check hotel prices and reward night availability at over 6.000 hotels worldwide - suitable for an intercontinental lifestyle. Please get in touch with the hotel company before using this software in production. Please also note that Trippe will **not** work 'out of the box' but needs a (static) API key to perform any request to the backend. | ||
Unofficial Node client to check hotel prices and reward night availability at over 6.000 hotels worldwide - suitable for an intercontinental lifestyle. Please get in touch with the hotel company before using this software in production. Please also note that Trippe will **not** work 'out of the box' but needs a (static) API key to perform any request to the backend. | ||
@@ -5,0 +5,0 @@ [![npm version](https://img.shields.io/npm/v/trippe)](https://www.npmjs.com/package/trippe) |
69777
457