Skip to content

Instantly share code, notes, and snippets.

@erdesigns-eu
Last active October 26, 2022 12:45
Show Gist options
  • Save erdesigns-eu/a20fcf7a377c9a12689365caf37456d6 to your computer and use it in GitHub Desktop.
Save erdesigns-eu/a20fcf7a377c9a12689365caf37456d6 to your computer and use it in GitHub Desktop.
NewsAPI Class for use in Browsers
/**
* 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