Last active
October 26, 2022 12:45
-
-
Save erdesigns-eu/a20fcf7a377c9a12689365caf37456d6 to your computer and use it in GitHub Desktop.
NewsAPI Class for use in Browsers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* News API Class for use in the browser. You can use this on localhost | |
* or if you have a paid subscription you can use it on your website. | |
* Just create a new instance and pass your API key, alternatively | |
* you can set some defaults via the options object. | |
* | |
* License: MIT | |
* Author: Ernst Reidinga - ERDesigns - 26/10/2022 | |
*/ | |
class NewsAPIError extends Error { | |
/** | |
* Create new NewsAPI Error instance | |
* @param {Object} error | |
*/ | |
constructor(error) { | |
super(); | |
this.code = error.code; | |
this.name = `NewsAPIError: ${error.code}`; | |
this.message = error.message; | |
} | |
} | |
export class NewsAPI { | |
#apiKey; | |
#apiURL = 'https://newsapi.org'; | |
#defaultCountry; | |
#defaultCategory; | |
#defaultSources; | |
#defaultPageSize; | |
#defaultLanguage; | |
/** | |
* Create new NewsAPI instance | |
* @param {String} apiKey | |
* @param {Object} options | |
*/ | |
constructor(apiKey, options = {}) { | |
// Check for API key | |
if (!apiKey || !apiKey.length) { | |
throw new Error('No API key specified!'); | |
} | |
// Set API key | |
this.#apiKey = apiKey; | |
// Default Country | |
this.#defaultCountry = (options && options.country) ? options.country : 'us'; | |
// Default Category | |
this.#defaultCategory = (options && options.category) ? options.category : ''; | |
// Default Sources | |
this.#defaultSources = (options && options.sources) ? options.sources : []; | |
// Default PageSize | |
this.#defaultPageSize = (options && options.pageSize) ? options.pageSize : 20; | |
// Default Language | |
this.#defaultLanguage = (options && options.language) ? options.language : 'en'; | |
} | |
/** | |
* HTTP Get Request | |
* @param {String} url | |
* @returns | |
*/ | |
#get(url) { | |
return new Promise((resolve, reject) => { | |
fetch(url) | |
.then(response => response.json()) | |
.then(data => resolve(data)) | |
.catch(error => reject(error)); | |
}); | |
} | |
/** | |
* This endpoint provides live top and breaking articles for a country, | |
* specific category in a country, single source, or multiple sources. | |
* You can also search with keywords. Articles are sorted by the earliest date published first. | |
* @param {Object} options | |
*/ | |
headlines(options = {}) { | |
const country = (options && options.country) ? options.country : this.#defaultCountry; | |
const category = (options && options.category) ? options.category : this.#defaultCategory; | |
const sources = (options && options.sources) ? options.sources.join() : this.#defaultSources.join(); | |
const search = (options && options.search) ? options.search : ''; | |
const pageSize = (options && options.pageSize) ? options.pageSize : this.#defaultPageSize; | |
const page = (options && options.page) ? options.page : 0; | |
// Build URL | |
const url = new URL('/v2/top-headlines', this.#apiURL); | |
// Country (Note: you can't mix this param with the sources param.) | |
if (!sources.length && country.length) { | |
url.searchParams.append('country', country); | |
} | |
// Category (Note: you can't mix this param with the sources param.) | |
if (!sources.length && category.length) { | |
url.searchParams.append('category', category); | |
} | |
// Sources (Note: you can't mix this param with the country or category params.) | |
if (sources.length) { | |
url.searchParams.append('sources', sources); | |
} | |
// Search (Keywords or a phrase to search for.) | |
if (search.length) { | |
url.searchParams.append('q', search); | |
} | |
// Page | |
if (page > 0) { | |
url.searchParams.append('page', page); | |
} | |
// Page Size | |
url.searchParams.append('pageSize', pageSize); | |
// API key | |
url.searchParams.append('apiKey', this.#apiKey); | |
// Get headlines | |
return new Promise((resolve, reject) => { | |
this.#get(url.href) | |
.then((result) => { | |
if (result.status === 'error') { | |
reject(new NewsAPIError(result)); | |
} else { | |
resolve(result.articles); | |
} | |
}) | |
.catch((error) => { | |
reject(error); | |
}); | |
}); | |
} | |
/** | |
* Search through millions of articles from over 80,000 large and small news sources and blogs. | |
* @param {Object} options | |
*/ | |
search(options = {}) { | |
const search = (options && options.search) ? options.search : ''; | |
const searchIn = (options && options.searchIn) ? options.searchIn.join() : ''; | |
const sources = (options && options.sources) ? options.sources.join() : ''; | |
const domains = (options && options.domains) ? options.domains.join() : ''; | |
const exclude = (options && options.exclude) ? options.exclude.join() : ''; | |
const from = (options && options.from) ? options.from.toISOString() : ''; | |
const to = (options && options.to) ? options.to.toISOString() : ''; | |
const language = (options && options.language) ? options.language : this.#defaultLanguage; | |
const sortBy = (options && options.sortBy) ? options.sortBy : 'publishedAt'; | |
const pageSize = (options && options.pageSize) ? options.pageSize : this.#defaultPageSize; | |
const page = (options && options.page) ? options.page : 0; | |
// Build URL | |
const url = new URL('/v2/everything', this.#apiURL); | |
// Search (Keywords or phrases to search for in the article title and body.) | |
if (search.length) { | |
url.searchParams.append('q', search); | |
} | |
// Search In (The fields to restrict your q search to.) | |
if (searchIn.length) { | |
url.searchParams.append('searchIn', searchIn); | |
} | |
// Sources (A comma-seperated string of identifiers (maximum 20) for the news sources or blogs you want headlines from.) | |
if (sources.length) { | |
url.searchParams.append('sources', sources); | |
} | |
// Domains (A comma-seperated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to restrict the search to.) | |
if (domains.length) { | |
url.searchParams.append('domains', domains); | |
} | |
// Exclude Domains (A comma-seperated string of domains (eg bbc.co.uk, techcrunch.com, engadget.com) to remove from the results.) | |
if (exclude.length) { | |
url.searchParams.append('excludeDomains', exclude); | |
} | |
// From (A date and optional time for the oldest article allowed.) | |
if (from.length) { | |
url.searchParams.append('from', from); | |
} | |
// To (A date and optional time for the newest article allowed.) | |
if (to.length) { | |
url.searchParams.append('to', to); | |
} | |
// Language (The 2-letter ISO-639-1 code of the language you want to get articles for.) | |
if (language.length) { | |
url.searchParams.append('language', language); | |
} | |
// Sort By (The order to sort the articles in.) | |
if (sortBy.length) { | |
url.searchParams.append('sortBy', sortBy); | |
} | |
if (page > 0) { | |
url.searchParams.append('page', page); | |
} | |
// Page Size () | |
url.searchParams.append('pageSize', pageSize); | |
// API key | |
url.searchParams.append('apiKey', this.#apiKey); | |
// Get search results | |
return new Promise((resolve, reject) => { | |
this.#get(url.href) | |
.then((result) => { | |
if (result.status === 'error') { | |
reject(new NewsAPIError(result)); | |
} else { | |
resolve(result.articles); | |
} | |
}) | |
.catch((error) => { | |
reject(error); | |
}); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment