"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.gotClient = exports.optionSetupAndSplit = exports.removeNestedUndefinedValues = exports.isThisANonHTMLUrl = exports.isImageTypeValid = exports.findImageTypeFromUrl = exports.validateAndFormatURL = exports.isUrlValid = void 0; const validator_1 = require("validator"); /** * Checks if URL is valid * * @param {string} url - url to be checked * @param {string} urlValidatorSettings - settings used by validator * @return {boolean} boolean value if the url is valid * */ function isUrlValid(url, urlValidatorSettings) { return typeof url === 'string' && url.length > 0 && validator_1.default.isURL(url, urlValidatorSettings); } exports.isUrlValid = isUrlValid; /** * Forces url to start with http:// if it doesn't * * @param {string} url - url to be updated * @return {string} url that starts with http * */ const coerceUrl = (url) => (/^(f|ht)tps?:\/\//i.test(url) ? url : `http://${url}`); /** * Validates and formats url * * @param {string} url - url to be checked and formatted * @param {string} urlValidatorSettings - settings used by validator * @return {string} proper url or null * */ function validateAndFormatURL(url, urlValidatorSettings) { return { url: isUrlValid(url, urlValidatorSettings) ? coerceUrl(url) : null }; } exports.validateAndFormatURL = validateAndFormatURL; /** * Finds the image type from a given url * * @param {string} url - url to be checked * @return {string} image type from url * */ function findImageTypeFromUrl(url) { let type = url.split('.').pop(); [type] = type.split('?'); return type; } exports.findImageTypeFromUrl = findImageTypeFromUrl; /** * Checks if image type is valid * * @param {string} type - type to be checked * @return {boolean} boolean value if type is value * */ function isImageTypeValid(type) { const validImageTypes = ['apng', 'bmp', 'gif', 'ico', 'cur', 'jpg', 'jpeg', 'jfif', 'pjpeg', 'pjp', 'png', 'svg', 'tif', 'tiff', 'webp']; return validImageTypes.includes(type); } exports.isImageTypeValid = isImageTypeValid; /** * Checks if URL is a non html page * * @param {string} url - url to be checked * @return {boolean} boolean value if url is non html * */ function isThisANonHTMLUrl(url) { const invalidImageTypes = ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.3gp', '.avi', '.mov', '.mp4', '.m4v', '.m4a', '.mp3', '.mkv', '.ogv', '.ogm', '.ogg', '.oga', '.webm', '.wav', '.bmp', '.gif', '.jpg', '.jpeg', '.png', '.webp', '.zip', '.rar', '.tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz2', '.txt', '.pdf']; const extension = findImageTypeFromUrl(url); return invalidImageTypes.some((type) => `.${extension}`.includes(type)); } exports.isThisANonHTMLUrl = isThisANonHTMLUrl; /** * Find and delete nested undefs * * @param {object} object - object to be cleaned * @return {object} object without nested undefs * */ function removeNestedUndefinedValues(object) { Object.entries(object).forEach(([key, value]) => { if (value && typeof value === 'object') removeNestedUndefinedValues(value); else if (value === undefined) delete object[key]; }); return object; } exports.removeNestedUndefinedValues = removeNestedUndefinedValues; /** * Split the options object into ogs and got option objects * * @param {object} options - options that need to be split * @return {object} object with nested options for ogs and got * */ function optionSetupAndSplit(options) { const ogsOptions = { allMedia: false, customMetaTags: [], downloadLimit: 1000000, ogImageFallback: true, onlyGetOpenGraphInfo: false, urlValidatorSettings: { allow_fragments: true, allow_protocol_relative_urls: false, allow_query_components: true, allow_trailing_dot: false, allow_underscores: false, protocols: ['http', 'https'], require_host: true, require_port: false, require_protocol: false, require_tld: true, require_valid_protocol: true, validate_length: true, }, ...options, }; const gotOptions = { decompress: true, followRedirect: true, headers: {}, maxRedirects: 10, ...options, }; // remove any OGS options from gotOptions since this will cause errors in got delete gotOptions.allMedia; delete gotOptions.blacklist; delete gotOptions.customMetaTags; delete gotOptions.downloadLimit; delete gotOptions.ogImageFallback; delete gotOptions.onlyGetOpenGraphInfo; delete gotOptions.urlValidatorSettings; return { ogsOptions, gotOptions }; } exports.optionSetupAndSplit = optionSetupAndSplit; /** * gotClient - limit the size of the content we fetch when performing the request * from https://github.com/sindresorhus/got/blob/main/documentation/examples/advanced-creation.js * * @param {string} downloadLimit - the download limit, will close connection once it is reached * @return {function} got client with download limit * */ async function gotClient(downloadLimit) { // https://github.com/sindresorhus/got/issues/1789 // eslint-disable-next-line import/no-unresolved const { got } = await import('got'); return got.extend({ handlers: [ (options, next) => { const promiseOrStream = next(options); const destroy = (message) => { if (options.isStream) { promiseOrStream.destroy(new Error(message)); return; } promiseOrStream.cancel(message); }; if (typeof downloadLimit === 'number') { promiseOrStream.on('downloadProgress', (progress) => { if (progress.transferred > downloadLimit && progress.percent !== 1) { destroy(`Exceeded the download limit of ${downloadLimit} bytes`); } }); } return promiseOrStream; }, ], }); } exports.gotClient = gotClient;