stackexchange-api
Version:
A Node.js wrapper for the StackExchange API
978 lines (977 loc) • 43.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const rp = require("request-promise");
const index_1 = require("../index");
const dateHandler_1 = require("../handlers/dateHandler");
const fieldHandler_1 = require("../handlers/fieldHandler");
const filterHandler_1 = require("../handlers/filterHandler");
const semiDelimitedListHandler_1 = require("../handlers/semiDelimitedListHandler");
class StackExchange {
/*
* A method for the /search/advanced endpoint: https://api.stackexchange.com/docs/advanced-search
* Searches a site for any questions which fit the given criteria.
* Search criteria are expressed using various parameters.
* At least one additional parameter must be set if `notTagged` is set, for performance reasons.
* The sorts accepted by this method operate on the following fields of the Question object:
* activity – lastActivityDate
* creation – creationDate
* votes – score
* relevance – matches the relevance tab on the site itself
* Does not accept min or max
* `activity` is the default sort.
* This method returns an array of questions (Question[]) wrapped in a Wrapper.
*/
static async advancedSearch(options) {
const advancedSearchUrl = new URL('/search/advanced', this.baseUrl);
if (options.accepted) {
advancedSearchUrl.searchParams.append('accepted', options.accepted.toString());
}
if (options.answers) {
advancedSearchUrl.searchParams.append('answers', options.answers.toString());
}
if (options.body) {
advancedSearchUrl.searchParams.append('body', options.body);
}
if (options.closed) {
advancedSearchUrl.searchParams.append('closed', options.closed.toString());
}
if (options.filter) {
advancedSearchUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
advancedSearchUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
advancedSearchUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.migrated) {
advancedSearchUrl.searchParams.append('migrated', options.migrated.toString());
}
if (options.min) {
advancedSearchUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.notice) {
advancedSearchUrl.searchParams.append('notice', options.notice.toString());
}
if (options.notTagged) {
if (options.tagged
|| options.q
|| options.title
|| options.body
|| options.url) {
advancedSearchUrl.searchParams.append('nottagged', semiDelimitedListHandler_1.semiDelimitedListHandler(options.notTagged));
}
else {
throw Error('`notTagged` requires one of `tagged`, `q`, `title`, `body`, or `url` to also be specified');
}
}
if (options.order) {
advancedSearchUrl.searchParams.append('order', options.order);
}
if (options.page) {
advancedSearchUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
advancedSearchUrl.searchParams.append('pagesize', options.pageSize.toString());
}
if (options.q) {
advancedSearchUrl.searchParams.append('q', options.q);
}
advancedSearchUrl.searchParams.append('site', options.site);
if (options.sort) {
advancedSearchUrl.searchParams.append('sort', options.sort);
}
if (options.tagged) {
advancedSearchUrl.searchParams.append('tagged', semiDelimitedListHandler_1.semiDelimitedListHandler(options.tagged));
}
if (options.title) {
advancedSearchUrl.searchParams.append('title', options.title);
}
if (options.toDate) {
advancedSearchUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
if (options.user) {
advancedSearchUrl.searchParams.append('user', options.user.toString());
}
if (options.url) {
advancedSearchUrl.searchParams.append('url', options.url);
}
if (options.views) {
advancedSearchUrl.searchParams.append('views', options.views.toString());
}
if (options.wiki) {
advancedSearchUrl.searchParams.append('wiki', options.wiki.toString());
}
return new index_1.Wrapper(await rp.get(advancedSearchUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Question');
}
static async createFilter(options) {
const createFilterUrl = new URL(`/filters/create`, this.baseUrl);
if (options.base) {
createFilterUrl.searchParams.append('base', options.base);
}
if (options.exclude) {
createFilterUrl.searchParams.append('exclude', fieldHandler_1.fieldHandler(options.exclude));
}
if (options.filter) {
createFilterUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.include) {
createFilterUrl.searchParams.append('include', fieldHandler_1.fieldHandler(options.include));
}
if (options.unsafe) {
createFilterUrl.searchParams.append('unsafe', options.unsafe.toString());
}
return new index_1.Wrapper(await rp.post(createFilterUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Filter');
}
static async decodeFilters(options) {
const decodeFiltersUrl = new URL(`/filters/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.filters)}`, this.baseUrl);
if (options.filter) {
decodeFiltersUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
return new index_1.Wrapper(await rp.get(decodeFiltersUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Filter');
}
/*
* A method for the /answers endpoint: https://api.stackexchange.com/docs/answers
* Returns all the undeleted answers in the system.
* The sorts accepted by this method operate on the following fields of the Answer object:
* activity – lastActivityDate
* creation – creationDate
* votes – score
* `activity` is the default sort.
* This method returns an array of answers (Answer[]) wrapped in a Wrapper.
*/
static async getAnswers(options) {
const getAnswersUrl = new URL('/answers', this.baseUrl);
if (options.filter) {
getAnswersUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getAnswersUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getAnswersUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getAnswersUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getAnswersUrl.searchParams.append('order', options.order);
}
if (options.page) {
getAnswersUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getAnswersUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getAnswersUrl.searchParams.append('site', options.site);
if (options.sort) {
getAnswersUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getAnswersUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getAnswersUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Answer');
}
/*
* A method for the /answers/{ids} endpoint: https://api.stackexchange.com/docs/answers-by-ids
* Gets the set of answers identified by ids.
* This is meant for batch fetching of questions.
* A useful trick to poll for updates is to sort by activity,
* with a minimum date of the last time you polled.
* `ids` can contain up to 100 semicolon delimited ids.
* To find ids programmatically look for answerId on Answer objects.
* The sorts accepted by this method operate on the following fields of the Answer object:
* activity – lastActivityDate
* creation – creationDate
* votes – score
* `activity` is the default sort.
* This method returns an array of answers (Answer[]) wrapped in a Wrapper.
*/
static async getAnswersByIds(options) {
const getAnswersByIdsUrl = new URL(`/answers/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.ids)}`, this.baseUrl);
if (options.filter) {
getAnswersByIdsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getAnswersByIdsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getAnswersByIdsUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getAnswersByIdsUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getAnswersByIdsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getAnswersByIdsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getAnswersByIdsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getAnswersByIdsUrl.searchParams.append('site', options.site);
if (options.sort) {
getAnswersByIdsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getAnswersByIdsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getAnswersByIdsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Answer');
}
/*
* A method for the /badges endpoint: https://api.stackexchange.com/docs/badges
* Returns all the badges in the system.
* This method returns an array of badges (Badge[]) wrapped in a Wrapper.
*/
static async getBadges(options) {
let getBadgesUrlPath = '/badges';
if (options.named) {
if (options.tagBased) {
throw Error('The `named` and `tagBased` options are mutually exclusive');
}
else {
getBadgesUrlPath += '/name';
}
}
if (options.tagBased) {
if (options.named) {
throw Error('The `named` and `tagBased` options are mutually exclusive');
}
else {
getBadgesUrlPath += '/tags';
}
}
const getBadgesUrl = new URL(getBadgesUrlPath, this.baseUrl);
if (options.filter) {
getBadgesUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getBadgesUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.inName) {
getBadgesUrl.searchParams.append('inname', options.inName);
}
if (options.max) {
getBadgesUrl.searchParams.append('max', options.max);
}
if (options.min) {
getBadgesUrl.searchParams.append('min', options.min);
}
if (options.order) {
getBadgesUrl.searchParams.append('order', options.order);
}
if (options.page) {
getBadgesUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getBadgesUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getBadgesUrl.searchParams.append('site', options.site);
if (options.sort) {
getBadgesUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getBadgesUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getBadgesUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Badge');
}
/*
* A method for the /badges/{ids} endpoint: https://api.stackexchange.com/docs/badges-by-ids
* Gets the badges identified in id.
* {ids} can contain up to 100 semicolon delimited ids.
* To find ids programmatically look for badgeId on Badge objects.
* This method returns an array of badges (Badge[]) wrapped in a Wrapper.
*/
static async getBadgesByIds(options) {
const getBadgesByIdsUrl = new URL(`/badges/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.ids)}`, this.baseUrl);
if (options.filter) {
getBadgesByIdsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getBadgesByIdsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getBadgesByIdsUrl.searchParams.append('max', options.max);
}
if (options.min) {
getBadgesByIdsUrl.searchParams.append('min', options.min);
}
if (options.order) {
getBadgesByIdsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getBadgesByIdsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getBadgesByIdsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getBadgesByIdsUrl.searchParams.append('site', options.site);
if (options.sort) {
getBadgesByIdsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getBadgesByIdsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getBadgesByIdsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Badge');
}
/*
* A method for the /badges/name endpoint: https://api.stackexchange.com/docs/badges-by-name
* Gets all explicitly named badges in the system.
* This method returns an array of badges (Badge[]) wrapped in a Wrapper.
*/
static getNamedBadges(options) {
return this.getBadges({
...options,
named: true,
});
}
/*
* A method for the /badges/tags endpoint: https://api.stackexchange.com/docs/badges-by-tag
* Returns the badges that are awarded for participation in specific tags.
* This method returns an array of badges (Badge[]) wrapped in a Wrapper.
*/
static getTagBasedBadges(options) {
return this.getBadges({
...options,
tagBased: true,
});
}
/*
* A method for the /badges/recipients endpoint: https://api.stackexchange.com/docs/badges-recipients
* Returns recently awarded badges in the system.
* As these badges have been awarded, they will have the Badge.user property set.
* This method returns an array of badges (Badge[]) wrapped in a Wrapper.
*/
static async getRecipientsBadges(options) {
const getRecipientsBadgesUrl = new URL('/badges/recipients', this.baseUrl);
if (options.filter) {
getRecipientsBadgesUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getRecipientsBadgesUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.page) {
getRecipientsBadgesUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getRecipientsBadgesUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getRecipientsBadgesUrl.searchParams.append('site', options.site);
if (options.toDate) {
getRecipientsBadgesUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getRecipientsBadgesUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Badge');
}
/*
* A method for the /badges/{ids}/recipients endpoint: https://api.stackexchange.com/docs/badges-recipients-by-ids
* Returns recently awarded badges in the system, constrained to a certain set of badges.
* As these badges have been awarded, they will have the Badge.user property set.
* {ids} can contain up to 100 semicolon delimited ids.
* To find ids programmatically look for badgeId on Badge objects.
* This method returns an array of badges (Badge[]) wrapped in a Wrapper.
*/
static async getRecipientsBadgesByIds(options) {
const getRecipientsBadgesByIdsUrl = new URL(`/badges/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.ids)}/recipients`, this.baseUrl);
if (options.filter) {
getRecipientsBadgesByIdsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getRecipientsBadgesByIdsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.page) {
getRecipientsBadgesByIdsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getRecipientsBadgesByIdsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getRecipientsBadgesByIdsUrl.searchParams.append('site', options.site);
if (options.toDate) {
getRecipientsBadgesByIdsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getRecipientsBadgesByIdsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Badge');
}
/*
* A method for the /comments endpoint: https://api.stackexchange.com/docs/comments
* Gets all the comments on the site.
* The sorts accepted by this method operate on the following fields of the Comment object:
* creation – creationDate
* votes – score
* `creation` is the default sort.
* This method returns an array of comments (Comment[]) wrapped in a Wrapper.
*/
static async getComments(options) {
const getCommentsUrl = new URL('/comments', this.baseUrl);
if (options.filter) {
getCommentsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getCommentsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getCommentsUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getCommentsUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getCommentsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getCommentsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getCommentsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getCommentsUrl.searchParams.append('site', options.site);
if (options.sort) {
getCommentsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getCommentsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getCommentsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Comment');
}
/*
* A method for the /comments/{ids} endpoint: https://api.stackexchange.com/docs/comments-by-ids
* Gets the comments identified in id.
* `ids` can contain up to 100 semicolon delimited ids.
* To find ids programmatically look for commentId on Comment objects.
* The sorts accepted by this method operate on the following fields of the Comment object:
* creation – creationDate
* votes – score
* `creation` is the default sort.
* This method returns an array of comments (Comment[]) wrapped in a Wrapper.
*/
static async getCommentsByIds(options) {
const getCommentsByIdsUrl = new URL(`/comments/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.ids)}`, this.baseUrl);
if (options.filter) {
getCommentsByIdsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getCommentsByIdsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getCommentsByIdsUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getCommentsByIdsUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getCommentsByIdsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getCommentsByIdsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getCommentsByIdsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getCommentsByIdsUrl.searchParams.append('site', options.site);
if (options.sort) {
getCommentsByIdsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getCommentsByIdsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getCommentsByIdsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Comment');
}
/*
* A method for the /answers/{ids}/comments endpoint: https://api.stackexchange.com/docs/comments-on-answers
* Gets the comments on a set of answers.
* `ids` can contain up to 100 semicolon delimited ids.
* To find ids programmatically look for answerId on Answer objects.
* The sorts accepted by this method operate on the following fields of the Comment object:
* creation – creationDate
* votes – score
* `creation` is the default sort.
* This method returns an array of comments (Comment[]) wrapped in a Wrapper.
*/
static async getCommentsOnAnswers(options) {
const getCommentsOnAnswersUrl = new URL(`/answers/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.ids)}/comments`, this.baseUrl);
if (options.filter) {
getCommentsOnAnswersUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getCommentsOnAnswersUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getCommentsOnAnswersUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getCommentsOnAnswersUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getCommentsOnAnswersUrl.searchParams.append('order', options.order);
}
if (options.page) {
getCommentsOnAnswersUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getCommentsOnAnswersUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getCommentsOnAnswersUrl.searchParams.append('site', options.site);
if (options.sort) {
getCommentsOnAnswersUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getCommentsOnAnswersUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getCommentsOnAnswersUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Comment');
}
/*
* A method for the /info endpoint: https://api.stackexchange.com/docs/info
* Returns a collection of statistics about the site.
* Data to facilitate per-site customization, discover related sites, and aggregate statistics is all returned by this method.
* This method returns an array of info objects (Info[]) wrapped in a Wrapper.
*/
static async getInfo(options) {
const getInfoUrl = new URL('/info', this.baseUrl);
if (options.filter) {
getInfoUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
getInfoUrl.searchParams.append('site', options.site);
return new index_1.Wrapper(await rp.get(getInfoUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Info');
}
static async getPosts(options) {
const getPostsUrl = new URL('/posts', this.baseUrl);
if (options.filter) {
getPostsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getPostsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getPostsUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getPostsUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getPostsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getPostsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getPostsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getPostsUrl.searchParams.append('site', options.site);
if (options.sort) {
getPostsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getPostsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getPostsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Post');
}
static async getPostsByIds(options) {
const getPostsByIdsUrl = new URL(`/posts/${semiDelimitedListHandler_1.semiDelimitedListHandler(options.ids)}`, this.baseUrl);
if (options.filter) {
getPostsByIdsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getPostsByIdsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
getPostsByIdsUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
getPostsByIdsUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.order) {
getPostsByIdsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getPostsByIdsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getPostsByIdsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getPostsByIdsUrl.searchParams.append('site', options.site);
if (options.sort) {
getPostsByIdsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getPostsByIdsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getPostsByIdsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Post');
}
/*
* A method for the /privileges endpoint: https://api.stackexchange.com/docs/privileges
* Returns the earnable privileges on a site.
* While fairly stable, over time they do change.
* New ones are introduced with new features,
* and the reputation requirements change as a site matures.
* This method returns an array of privileges (Privilege[]) wrapped in a Wrapper.
*/
static async getPrivileges(options) {
const getPrivilegesUrl = new URL('/privileges', this.baseUrl);
if (options.filter) {
getPrivilegesUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.page) {
getPrivilegesUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getPrivilegesUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getPrivilegesUrl.searchParams.append('site', options.site);
return new index_1.Wrapper(await rp.get(getPrivilegesUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Privilege');
}
/*
* A method for the /sites endpoint: https://api.stackexchange.com/docs/sites
* Returns all sites in the network.
* This method returns an array of sites (Site[]) wrapped in a Wrapper.
*/
static async getSites(options) {
const getSitesUrl = new URL('/sites', this.baseUrl);
if (options.filter) {
getSitesUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.page) {
getSitesUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getSitesUrl.searchParams.append('pagesize', options.pageSize.toString());
}
return new index_1.Wrapper(await rp.get(getSitesUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Site');
}
/*
* A method for the /tags endpoint: https://api.stackexchange.com/docs/tags
* Returns the tags found on a site.
* The inName parameter lets a consumer filter down to tags
* that contain a certain substring.
* For example, inName: 'own' would return both 'download' and 'owner' amongst others.
* The sorts accepted by this method operate on the following fields of the Tag object:
* popular – count
* activity – the creationDate of the last Question asked with the tag
* name – name
* `popular` is the default sort.
* This method returns an array of tags (Tag[]) wrapped in a Wrapper.
*/
static async getTags(options) {
let getTagsUrlPath = '/tags';
if (options.moderatorOnly) {
if (options.required) {
throw Error('The `moderatorOnly` and `required` options are mutually exclusive');
}
else {
getTagsUrlPath += '/moderator-only';
}
}
if (options.required) {
if (options.moderatorOnly) {
throw Error('The `moderatorOnly` and `required` options are mutually exclusive');
}
else {
getTagsUrlPath += '/required';
}
}
const getTagsUrl = new URL(getTagsUrlPath, this.baseUrl);
if (options.filter) {
getTagsUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
getTagsUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.inName) {
getTagsUrl.searchParams.append('inname', options.inName);
}
if (options.max) {
getTagsUrl.searchParams.append('max', options.max.toString());
}
if (options.min) {
getTagsUrl.searchParams.append('min', options.min.toString());
}
if (options.order) {
getTagsUrl.searchParams.append('order', options.order);
}
if (options.page) {
getTagsUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
getTagsUrl.searchParams.append('pagesize', options.pageSize.toString());
}
getTagsUrl.searchParams.append('site', options.site);
if (options.sort) {
getTagsUrl.searchParams.append('sort', options.sort);
}
if (options.toDate) {
getTagsUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(getTagsUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Tag');
}
/*
* A method for the /tags/moderator-only endpoint: https://api.stackexchange.com/docs/moderator-only-tags
* Returns the tags found on a site that only moderators can use
* Accepts the same options as the getTags() method, minus `moderatorOnly` and `required`
* This method returns an array of tags (Tag[]) wrapped in a Wrapper.
*/
static getModeratorOnlyTags(options) {
return this.getTags({
...options,
moderatorOnly: true,
});
}
/*
* A method for the /tags/required endpoint: https://api.stackexchange.com/docs/required-tags
* Returns the tags found on a site that fulfill required tag constraints on questions.
* Accepts the same options as the getTags() method, minus `moderatorOnly` and `required`
* This method returns an array of tags (Tag[]) wrapped in a Wrapper.
*/
static getRequiredTags(options) {
return this.getTags({
...options,
required: true,
});
}
/*
* A method for the /search endpoint: https://api.stackexchange.com/docs/search
* Searches a site for any questions which fit the given criteria.
* At least one of `tagged` or `inTitle` must be set on this method.
* `notTagged` is only used if `tagged` is also set, for performance reasons.
* The sorts accepted by this method operate on the following fields of the Question object:
* activity – lastActivityDate
* creation – creationDate
* votes – score
* relevance – matches the relevance tab on the site itself
* Does not accept min or max
* `activity` is the default sort.
* This method returns an array of questions (Question[]) wrapped in a Wrapper.
*/
static async search(options) {
const searchUrl = new URL('/search', this.baseUrl);
if (options.filter) {
searchUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
searchUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.inTitle) {
searchUrl.searchParams.append('intitle', options.inTitle);
}
else if (!options.tagged) {
throw Error('At least one of `tagged` or `inTitle` must be set');
}
if (options.max) {
searchUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
searchUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.notTagged) {
if (options.tagged) {
searchUrl.searchParams.append('nottagged', semiDelimitedListHandler_1.semiDelimitedListHandler(options.notTagged));
}
else {
throw Error('`notTagged` may only be set if `tagged` is also set');
}
}
if (options.order) {
searchUrl.searchParams.append('order', options.order);
}
if (options.page) {
searchUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
searchUrl.searchParams.append('pagesize', options.pageSize.toString());
}
searchUrl.searchParams.append('site', options.site);
if (options.sort) {
if (options.sort === 'relevance' && (options.max || options.min)) {
throw Error('When `sort` is set to "relevance", the search method does not accept `min` or `max`');
}
searchUrl.searchParams.append('sort', options.sort);
}
if (options.tagged) {
searchUrl.searchParams.append('tagged', semiDelimitedListHandler_1.semiDelimitedListHandler(options.tagged));
}
else if (!options.inTitle) {
throw Error('At least one of `tagged` or `inTitle` must be set');
}
if (options.toDate) {
searchUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(searchUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Question');
}
/*
* A method for the /similar endpoint: https://api.stackexchange.com/docs/similar
* Returns questions which are similar to a hypothetical one based on a title and tag combination.
* This method is roughly equivalent to a site's related questions suggestion on the ask page.
* This method is useful for correlating data outside of a Stack Exchange site with similar content within one.
* Note that `title` must always be passed as a parameter. `tagged` and `notTagged` are optional, semi-colon delimited lists of tags.
* If `tagged` is passed it is treated as a preference, there is no guarantee that questions returned will have any of those tags. `notTagged` is treated as a requirement, no questions will be returned with those tags.
* The sorts accepted by this method operate on the following fields of the Question object:
* activity – last_activity_date
* creation – creation_date
* votes – score
* relevance – order by "how similar" the questions are, most likely candidate first with a descending order
* Does not accept min or max
* `activity` is the default sort.
* This method returns an array of questions (Question[]) wrapped in a Wrapper.
*/
static async similarSearch(options) {
const similarSearchUrl = new URL('/similar', this.baseUrl);
if (options.filter) {
similarSearchUrl.searchParams.append('filter', filterHandler_1.filterHandler(options.filter));
}
if (options.fromDate) {
similarSearchUrl.searchParams.append('fromdate', dateHandler_1.dateHandler(options.fromDate));
}
if (options.max) {
similarSearchUrl.searchParams.append('max', dateHandler_1.dateHandler(options.max));
}
if (options.min) {
similarSearchUrl.searchParams.append('min', dateHandler_1.dateHandler(options.min));
}
if (options.notTagged) {
similarSearchUrl.searchParams.append('nottagged', semiDelimitedListHandler_1.semiDelimitedListHandler(options.notTagged));
}
if (options.order) {
similarSearchUrl.searchParams.append('order', options.order);
}
if (options.page) {
similarSearchUrl.searchParams.append('page', options.page.toString());
}
if (options.pageSize) {
similarSearchUrl.searchParams.append('pagesize', options.pageSize.toString());
}
similarSearchUrl.searchParams.append('site', options.site);
if (options.sort) {
if (options.sort === 'relevance' && (options.max || options.min)) {
throw Error('When `sort` is set to "relevance", the search method does not accept `min` or `max`');
}
similarSearchUrl.searchParams.append('sort', options.sort);
}
if (options.tagged) {
similarSearchUrl.searchParams.append('tagged', semiDelimitedListHandler_1.semiDelimitedListHandler(options.tagged));
}
similarSearchUrl.searchParams.append('title', options.title);
if (options.toDate) {
similarSearchUrl.searchParams.append('todate', dateHandler_1.dateHandler(options.toDate));
}
return new index_1.Wrapper(await rp.get(similarSearchUrl.href, {
headers: {
'accept-encoding': 'gzip',
},
gzip: true,
json: true,
}), 'Question');
}
}
exports.StackExchange = StackExchange;
StackExchange.baseUrl = new URL('https://api.stackexchange.com/2.2');