reddit-simple-client
Version:
Simple module for interacting with Reddit, using oauth to authenticate to the reddit api
178 lines (151 loc) • 5.8 kB
JavaScript
import { DefaultOptions } from './reddit/modal/reddit-options.js';
import { SORT_TYPE } from './reddit/modal/sort-type.js';
import { CreateAuth } from './reddit/reddit-auth.js';
import log from './util/log.js';
import parseJSON from './util/parse-json.js';
import { parsePostArray, parseCommentArray } from './util/reddit/reddit-parser.js';
import { getValidValue } from './util/util.js';
// This is the max number of posts Reddit allows to be retrieved at once. If a higher number is used, this is used anyway
export const MAX_NUM_POSTS = 100;
export const MIN_NUM_POSTS = 1;
export const MAX_NUM_COMMENTS = 1000;
export const MIN_NUM_COMMENTS = 10;
const REDDIT_OBJECT = {
COMMENT: 'COMMENT',
POST: 'POST'
};
export class RedditClient {
constructor({ redditOptions = DefaultOptions, redditAuth }) {
this.redditOptions = redditOptions;
this.redditAuth = redditAuth;
}
/**
* Returns posts from subreddit
*
* @param numberOfPosts {int | MIN_NUM_POSTS} number of posts to retrieve, between 1-100
* @param subreddit {string} subreddit to get posts from
* @param sortType {SORT_TYPE | SORT_TYPE.NEW} E.G 'new', or 'hot'
* @return Promise containing a list of RedditPost objects
*/
async getPostsFromSubreddit({
numberOfPosts = MIN_NUM_POSTS,
subreddit,
sortType = SORT_TYPE.NEW
}) {
numberOfPosts = getValidNumberOfPosts(numberOfPosts);
const path = '/r/' + subreddit + "/" + sortType + ".json?limit=" + numberOfPosts;
const dataFromUrl = await this.redditAuth.getListing(path);
log.debug(dataFromUrl);
return await getPostObjectsFromRawURLData(dataFromUrl, this.redditOptions.useSimpleReturnValues);
}
/**
* Get a list of the newest comments from Reddit
*
* @param numberOfComments {int | MAX_NUM_COMMENTS} A number between 10-1000 (between 1-9 does not work for Reddit)
* @param options {redditOptions} reddit options
* @return List of comment objects
*/
async getLatestCommentsFromReddit({
numberOfComments = MAX_NUM_COMMENTS,
subreddit = 'all'
} = {}) {
numberOfComments = getValidNumberOfComments(numberOfComments);
const path = `/r/${subreddit}/comments.json?limit=${numberOfComments}`;
const dataFromUrl = await this.redditAuth.getListing(path);
log.debug(dataFromUrl);
return await getCommentObjectFromRawURLData(dataFromUrl, this.redditOptions.useSimpleReturnValues);
}
/**
* Gets a list of the names of moderators for the subreddit
*
* @param subreddit
* @return Promise containing list of moderator usernames
*/
async getSubredditModList(subreddit) {
const path = `/r/${subreddit}/about/moderators.json`;
const dataFromUrl = await this.redditAuth.getListing(path);
const jsonData = parseJSON(dataFromUrl);
log.debug(jsonData);
if (jsonData && jsonData.data) {
log.debug(jsonData.data);
return jsonData.data.children;
}
return jsonData;
}
async postComment(commentId, textToComment) {
log.info('trying to post comment : ' + textToComment + ' with id: ' + commentId);
return await this.redditAuth.postComment(commentId, textToComment);
}
async resetAuth() {
await this.redditAuth.getAuth();
}
}
export async function CreateAuthedClient({ redditOptions, redditAuth }) {
const redditClient = new RedditClient({ redditOptions, redditAuth });
redditClient.redditAuth = await CreateAuth({ redditAuth });
return redditClient;
}
/**
* Returns an object based on the data returned from a Reddit URL.
*
* @param rawDataFromURL Data from a Reddit URL, containing all the comment info
* @param {boolean | false} useSimpleValues
* @return An array of Post objects containing body, subreddit etc
*/
function getPostObjectsFromRawURLData(rawDataFromURL, useSimpleObjects = false) {
return getObjectFromRawData(rawDataFromURL, REDDIT_OBJECT.POST, useSimpleObjects);
}
/**
* Returns an object based on the data returned from a Reddit URL.
*
* @param rawDataFromURL Data from a Reddit URL, containing all the comment info
* @param {boolean | false} useSimpleValues
* @return A Comment object containing body, subreddit etc
*/
function getCommentObjectFromRawURLData(rawDataFromURL, useSimpleObjects = false) {
return getObjectFromRawData(rawDataFromURL, REDDIT_OBJECT.COMMENT, useSimpleObjects);
}
/**
*
* @param {string} rawDataFromURL
* @param {REDDIT_OBJECT} redditType
* @param {boolean | false} useSimpleValues
*/
function getObjectFromRawData(rawDataFromURL, redditType, useSimpleValues = false) {
const jsonDataFromUrl = parseJSON(rawDataFromURL);
if (!jsonDataFromUrl.data || !jsonDataFromUrl.data.children) {
return jsonDataFromUrl;
}
const result = jsonDataFromUrl.data.children.map(post => {
if (!useSimpleValues) {
return post.data;
}
switch (redditType) {
case REDDIT_OBJECT.COMMENT:
return parseCommentArray(post);
case REDDIT_OBJECT.POST:
return parsePostArray(post);
default:
throw 'Unknown reddit type: ' + redditType;
}
});
return result;
}
/**
* This is what happens anyway. Reddit accepts numbers over 100 as 100 and less then 1 as 1
*
* @param numberOfPosts
* @return
*/
function getValidNumberOfPosts(numberOfPosts) {
return getValidValue(numberOfPosts, MIN_NUM_POSTS, MAX_NUM_POSTS, MIN_NUM_POSTS);
}
/**
* Reddit accepts numbers over 1000 as 1000 and less then 1 as 1
*
* @param numberOfPosts
* @return
*/
function getValidNumberOfComments(numberOfComments) {
return getValidValue(numberOfComments, MIN_NUM_COMMENTS, MAX_NUM_COMMENTS, MAX_NUM_COMMENTS);
}