audible-api
Version:
A Node.js API for searching the audible website
306 lines (251 loc) • 13.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = searchAudible;
var _cheerio = require("cheerio");
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
var _url = require("url");
var _audibleSearchFields = require("./data/audible-search-fields");
var _getAudibleBook = _interopRequireDefault(require("./get-audible-book"));
var _language = require("./utils/language");
var _string = require("./utils/string");
var _time = require("./utils/time");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
/**
* Search the Audible website for a list of books matching your search criteria
*
* @param options - An object containing your search criteria
* @returns A promise returning an array of book objects from the search results, along with total results
*/
function searchAudible() {
return _searchAudible.apply(this, arguments);
}
function _searchAudible() {
_searchAudible = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
var _ref,
keywords,
title,
author,
narrator,
publisher,
category,
_ref$isAudibleOrigina,
isAudibleOriginal,
_ref$isPlusCatalog,
isPlusCatalog,
releaseTime,
_ref$durations,
durations,
_ref$languages,
languages,
_ref$isWhisperSync,
isWhisperSync,
isAbridged,
_ref$pageNum,
pageNum,
_ref$pageSize,
pageSize,
_ref$getFull,
getFull,
_ref$site,
site,
_ref2,
baseUrl,
baseSearchUrl,
realPageSize,
paramsObj,
params,
searchUrl,
res,
body,
page,
audibleItems,
resultsStr,
totalResultsMatch,
totalResults,
searchResults,
_args = arguments;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_ref = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, keywords = _ref.keywords, title = _ref.title, author = _ref.author, narrator = _ref.narrator, publisher = _ref.publisher, category = _ref.category, _ref$isAudibleOrigina = _ref.isAudibleOriginal, isAudibleOriginal = _ref$isAudibleOrigina === void 0 ? false : _ref$isAudibleOrigina, _ref$isPlusCatalog = _ref.isPlusCatalog, isPlusCatalog = _ref$isPlusCatalog === void 0 ? false : _ref$isPlusCatalog, releaseTime = _ref.releaseTime, _ref$durations = _ref.durations, durations = _ref$durations === void 0 ? [] : _ref$durations, _ref$languages = _ref.languages, languages = _ref$languages === void 0 ? [] : _ref$languages, _ref$isWhisperSync = _ref.isWhisperSync, isWhisperSync = _ref$isWhisperSync === void 0 ? false : _ref$isWhisperSync, isAbridged = _ref.isAbridged, _ref$pageNum = _ref.pageNum, pageNum = _ref$pageNum === void 0 ? 1 : _ref$pageNum, _ref$pageSize = _ref.pageSize, pageSize = _ref$pageSize === void 0 ? 20 : _ref$pageSize, _ref$getFull = _ref.getFull, getFull = _ref$getFull === void 0 ? false : _ref$getFull, _ref$site = _ref.site, site = _ref$site === void 0 ? "us" : _ref$site;
_ref2 = _audibleSearchFields.siteCountries[site] || _audibleSearchFields.siteCountries.us, baseUrl = _ref2.url;
baseSearchUrl = "".concat(baseUrl, "/search");
realPageSize = _audibleSearchFields.pageSizes.includes(pageSize) ? pageSize : _audibleSearchFields.pageSizes[0];
paramsObj = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, title && {
title: title
}), keywords && {
keywords: keywords
}), author && {
searchAuthor: author
}), narrator && {
narrator: narrator
}), publisher && {
publisher: publisher
}), isAbridged === true && _audibleSearchFields.abridged), isAbridged === false && _audibleSearchFields.unabridged), isAudibleOriginal && _audibleSearchFields.audibleOriginal), isPlusCatalog && _audibleSearchFields.plusCatalog), isWhisperSync && _audibleSearchFields.whispersync), {}, {
page: pageNum.toString(),
pageSize: realPageSize.toString(),
ipRedirectOverride: "true"
}, _audibleSearchFields.audiobookFormat);
params = new _url.URLSearchParams(paramsObj);
if (releaseTime && _audibleSearchFields.releaseTimes[releaseTime]) {
params.append("publication_date", _audibleSearchFields.releaseTimes[releaseTime]);
}
if (category && _audibleSearchFields.searchCategories[category]) {
params.append("node", _audibleSearchFields.searchCategories[category]);
}
durations.forEach(function (duration) {
if (_audibleSearchFields.searchDurations[duration]) {
params.append("feature_seven_browse-bin", _audibleSearchFields.searchDurations[duration]);
}
});
languages.forEach(function (lang) {
var langCode = _audibleSearchFields.searchLanguages[lang.toLowerCase()];
if (langCode) {
params.append("feature_six_browse-bin", langCode);
}
});
searchUrl = "".concat(baseSearchUrl, "?").concat(params.toString());
_context.next = 13;
return (0, _nodeFetch["default"])(searchUrl);
case 13:
res = _context.sent;
_context.next = 16;
return res.text();
case 16:
body = _context.sent;
page = (0, _cheerio.load)(body);
audibleItems = [];
resultsStr = page(".resultsSummarySubheading").eq(0).text().trim();
totalResultsMatch = resultsStr.match(/([0-9,]+) results$/);
totalResults = totalResultsMatch ? Number(totalResultsMatch[1]) : 0;
page(".productListItem").each(function (i, elSel) {
var _newBook$url;
var newBook = {
title: page("h3", elSel).text().trim(),
coverUrl: page("img", elSel).attr("data-lazy"),
authors: [],
narrators: []
}; // Get book's language
var newLanguage = (0, _language.parseLanguage)(page(".languageLabel", elSel).text().replace("Language:", "").trim());
if (newLanguage) {
newBook.language = newLanguage;
} // Get book's url
var urlStr = page("h3 a", elSel).attr("href");
if (urlStr) {
newBook.url = (0, _string.cleanUrl)(new _url.URL(urlStr, baseUrl).href);
} // Get book's clean title
if (newBook.title) {
newBook.cleanTitle = (0, _string.cleanTitle)(newBook.title);
} // Get the book's duration
var runtimeStr = page(".runtimeLabel", elSel).text().trim();
if (runtimeStr) {
newBook.duration = (0, _time.getDurationFromStr)(runtimeStr);
} // Get the book's ASIN
var asinMatch = (_newBook$url = newBook.url) === null || _newBook$url === void 0 ? void 0 : _newBook$url.match(/\/([A-Z0-9]+)$/);
if (asinMatch) {
newBook.asin = asinMatch[1];
} // Get the aggregate rating
var ratingValueStr = page(".ratingsLabel .bc-pub-offscreen", elSel).text().trim();
var ratingsValueMatch = ratingValueStr.match(/[0-9.]+/);
var ratingValue = Number((ratingsValueMatch === null || ratingsValueMatch === void 0 ? void 0 : ratingsValueMatch[0]) || 0);
var ratingCountStr = page(".ratingsLabel .bc-color-secondary", elSel).text().trim();
var ratingCountMatch = ratingCountStr.match(/[0-9,]+/);
var ratingCount = Number((ratingCountMatch === null || ratingCountMatch === void 0 ? void 0 : ratingCountMatch[0].replace(/,/g, "")) || 0);
newBook.rating = {
value: ratingValue,
count: ratingCount
};
page(".authorLabel a", elSel).each(function (ii, authorSel) {
var authorEl = page(authorSel);
var newAuthor = {
name: authorEl.text().trim()
};
var authorUrlPath = authorEl.attr("href");
if (authorUrlPath) {
newAuthor.url = (0, _string.cleanUrl)(new _url.URL(authorUrlPath, baseUrl).href);
}
newBook.authors.push(newAuthor);
});
page(".authorLabel a", elSel).each(function (ii, narratorSel) {
var narratorEl = page(narratorSel);
var newNarrator = {
name: narratorEl.text().trim()
};
var narratorUrlPath = narratorEl.attr("href");
if (narratorUrlPath) {
newNarrator.url = (0, _string.cleanNarratorUrl)(new _url.URL(narratorUrlPath, baseUrl).href);
}
newBook.narrators.push(newNarrator);
}); // Get series and series part
try {
var series = [];
page(".seriesLabel a", elSel).each(function (iii, seriesSel) {
var el = page(seriesSel);
var newSeries = {
name: el.text().trim()
};
var seriesUrlPath = el.attr("href");
if (seriesUrlPath) {
newSeries.url = (0, _string.cleanUrl)(new _url.URL(seriesUrlPath, baseUrl).href);
}
series.push(newSeries);
});
var seriesArr = page(".seriesLabel", elSel).text().replace(/\n/g, "").trim() // remove the beginning text from the series
.replace("Series: ", "").split(", ").map(function (item) {
return item.trim();
});
seriesArr.forEach(function (seriesStr, seriesI) {
if (seriesStr.includes("Book")) {
var seriesPart = Number(seriesStr.replace("Book ", ""));
if (seriesPart) {
var matchingBookIndex = series.findIndex(function (item) {
return item.name === seriesArr[seriesI - 1];
});
if (matchingBookIndex > -1) {
series[matchingBookIndex].part = seriesPart;
}
}
}
});
newBook.series = series;
} catch (err) {// console.warn(`ERROR PARSING AUDIBLE SERIES'\n${err.stack}`);
}
audibleItems.push(newBook);
});
if (!getFull) {
_context.next = 27;
break;
}
_context.next = 26;
return Promise.all(audibleItems.map(function (book) {
return book.asin ? (0, _getAudibleBook["default"])(book.asin, {
site: site
}) : book;
}));
case 26:
audibleItems = _context.sent;
case 27:
// console.log(JSON.stringify(audibleItems, null, 2));
searchResults = {
totalResults: totalResults,
results: audibleItems
};
return _context.abrupt("return", searchResults);
case 29:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return _searchAudible.apply(this, arguments);
}
//# sourceMappingURL=search-audible.js.map