UNPKG

get-wikipedia-article

Version:

Fetch Wikipedia article resources (e.g. title, body, links...).

128 lines (109 loc) 4.07 kB
import CustomError from 'fullfiller-common/src/CustomError'; import { wikipediaLanguages } from 'fullfiller-common/src/constants'; import { articleIsDisambiguation, invalidLanguage, } from 'fullfiller-common/src/errorMessages'; import { articleType, formatType, termsType, wikipediaLanguageType as languageType, } from 'fullfiller-common/src/types'; import { includeType } from './common/types'; import extractSummaryFromBody from './extractSummaryFromBody'; import getArticleBody from './getArticleBody'; import getArticleCategories from './getArticleCategories'; import getArticleLinks from './getArticleLinks'; import getArticleSummary from './getArticleSummary'; import getArticleTerms from './getArticleTerms'; import getMatchingArticlesTitles from './getMatchingArticlesTitles'; import queryPointsToADisambiguationPage from './queryPointsToADisambiguationPage'; type optionsType = Partial<{ language: languageType; include: includeType; format: formatType; }>; const includeDefault: includeType = ['title', 'body']; /** * Fetch Wikipedia article's resources (e.g. title, body, links...). * @param query Search string. * @param options Miscellaneous options. * @throws Error if `query` doesn't return any results. * @throws Error if `article.title` points to a disambiguation page. * @returns Object containing requested resources. */ async function getWikipediaArticle( query: string, { language = 'en', include = includeDefault, format = 'plain', }: optionsType = {} ): Promise<articleType> { if (!Object.keys(wikipediaLanguages).includes(language)) { throw new CustomError( invalidLanguage(language, Object.keys(wikipediaLanguages)), 'get-wikipedia-article' ); } if (include.length === 0) include.push(...includeDefault); const article: articleType = {}; // fetch title, related if (include.includes('title') && include.includes('related')) { // first result will be selected as the article to be fetched const [title, ...related] = await getMatchingArticlesTitles( language, query ); article.title = title; article.related = related; } else if (include.includes('title')) { const [title] = await getMatchingArticlesTitles(language, query); article.title = title; } else if (include.includes('related')) { const [, ...related] = await getMatchingArticlesTitles(language, query); article.related = related; } // API calls to `action=query` using `query` instead of `article.title` // are allowed because `redirects` parameter is being used const titleQuery = article.title || query; // the only option other than to make a separate request at main function checking if page is // disambiguation, would be to check if page is disambiguation at every resource request if (await queryPointsToADisambiguationPage(language, titleQuery)) { throw new CustomError( articleIsDisambiguation(article.related || [] /* suggestions */), 'get-wikipedia-article' ); } // fetch body if (include.includes('body')) { article.body = await getArticleBody(language, titleQuery, format); } // fetch summary if (include.includes('summary')) { article.summary = article.body ? extractSummaryFromBody(article.body, format) : await getArticleSummary(language, titleQuery, format); } // fetch categories if (include.includes('categories')) { article.categories = await getArticleCategories(language, titleQuery); } // fetch links if (include.includes('links')) { article.links = await getArticleLinks(language, titleQuery); } // fetch terms const termsToInclude = ( ['alias', 'label', 'description'] as (keyof termsType)[] ).filter((term) => include.includes(term)); if (termsToInclude.length > 0) { const terms = await getArticleTerms(language, titleQuery, termsToInclude); (Object.keys(terms) as (keyof termsType)[]).forEach((term) => { article[term] = terms[term]; }); } return article; } export default getWikipediaArticle;