Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
reddit-explorer
Advanced tools
Simple reddit client that allows to fetch reddit names and content from any subreddit, without any account authentication.
reddit-explorer is a reddit client that allows you to fetch subreddit content easily. It only has 2 dependencies (typescript & axios).
To see what has been done on each version, you can consult the CHANGELOG.
npm install reddit-explorer
or
yarn add reddit-explorer
You have to pass your app credentials, see how to generate some:
At the bottom of the page click "create another app...", fill all the fields and then click "create app". You now see your clientId and secret.
For the moment reddit-explorer has 4 features:
access_token
string
I'm actively working on other features that are coming soon :)
import { createRedditClient, SortingMethod, TimeRange, PostFilter, moreThanNComments } from "reddit-explorer"
const reddit = createRedditClient({
clientId: "<clientId>",
secret: "<secret>",
})
You usually do not need this method, but can be useful if you want to see the authentication detail.
reddit.getAccessToken()
// {
// "access_token": "-QFrCA5GkksABCEibAakz2fQbzUE62A", <-- You can use this an put it in the next bearer token's request
// "token_type": "bearer",
// "device_id": "5f615d62-fa4c-11eb-b8bc-0242ac130003",
// "expires_in": 86400,
// "scope": "*"
// }
reddit.getSubredditNames({ query: "photo" })
.then((res) => console.log("photo", res))
// photo {
// names: [
// 'photo',
// 'photoshopbattles',
// 'photography',
// 'photocritique',
// 'photoshop',
// 'PhotoshopRequest',
// 'PhotoshopTutorials',
// 'photographs',
// 'photomarket',
// 'Photography101'
// ]
// }
There are three ways to achieve that:
import { createRedditClient } from "reddit-explorer"
const reddit = createRedditClient({
clientId: "<clientId>",
secret: "<secret>",
matureContent: true,
})
reddit.getSubredditNames({ query: "photo", include_over_18: true })
.then((res) => console.log("photo", res))
reddit.config.setMatureContent(true)
You have to pass a name and a SortingMethod
. Sorting method can be: Hot
, New
, Random
, Rising
, Top
or
Controversial
.
If the sorting method is Top
or Controversial
, you can also pass a TimeRange
. Time range can be: Hour
, Day
,
Week
, Month
, Year
, All
.
The package offers the type SubredditData
which is the type of all the [Object]
below (see at the end of the readme).
reddit
.getSubreddit({
name: "meme",
sortMethod: SortingMethod.New,
})
.then((res) => console.log("meme", res))
// meme {
// kind: 'Listing',
// data: {
// after: 't3_u9osas',
// dist: 25,
// modhash: '',
// geo_filter: '',
// children: [
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object], [Object], [Object],
// [Object]
// ],
// before: null
// }
// }
// Example with a TimeRange:
reddit
.getSubreddit({
name: "meme",
sortMethod: SortingMethod.Top,
t: TimeRange.Day,
})
.then((res) => console.log("meme", res))
If you want to keep only specific posts in the response, you can use postFilters
when creating the client. This
attribute accepts an array of functions, each one taking a SubredditData
into parameter and returning a boolean
,
(see the type PostFilter
). The package also comes with multiple PostFilterCreator
's, which are basically functions
that return a PostFilter
, such as moreThanNComments(100)
below:
const moreThan2Crossposts: PostFilter = (subredditData) => subredditData.num_crossposts > 2
const clientShowingOnlyPopularPosts = createRedditClient({
clientId: secrets.clientId,
secret: secrets.secret,
postFilters: [moreThanNComments(100), moreThan2Crossposts],
})
The API can only load a max amount of 100 posts (the default is 25). To load the next posts, you have to pass the after
param.
You can find the value of the after
in the previous response of the request you made, in response.after
. It contains
the name
(SubredditData.name
) of the last post in the previous call.
reddit
.getSubreddit({
name: "meme",
sortMethod: SortingMethod.New,
after: "t3_u9osas", // response.after of the previous call
})
.then((res) => console.log("meme", res))
If you do not want to memorize the after
attribute of the last response yourself, you can let the package handle it for
you, using getSubredditIterator
:
const memeSubredditIterator = reddit.getSubredditIterator({
name: "meme",
sortMethod: SortingMethod.New,
limit: 5,
})
const memeResults0To4 = await memeSubredditIterator.next()
const memeResults5To9 = await memeSubredditIterator.next()
console.log("memeResults0To4", memeResults0To4.value)
console.log("memeResults5To9", memeResults5To9.value)
// memeResults0To4 {
// kind: 'Listing',
// data: {
// after: 't3_uaslor',
// dist: 5,
// modhash: '',
// geo_filter: '',
// children: [ [Object], [Object], [Object], [Object], [Object] ],
// before: null
// }
// }
// memeResults5To9 {
// kind: 'Listing',
// data: {
// after: 't3_uas9sy',
// dist: 5,
// modhash: '',
// geo_filter: '',
// children: [ [Object], [Object], [Object], [Object], [Object] ],
// before: null
// }
// }
Instead of passing a string
to the name
argument, you can pass a string[]
to it:
const res = await client.getSubreddit({
sortMethod: SortingMethod.Top,
name: ["news", "meme"],
})
createRedditSimpleClient
allows to get only the essential. This client will return a modified response containing only:
For the moment, the simple client only supports getSubreddit
and getSubredditNames
.
const reddit = createRedditSimpleClient({
clientId: "<clientId>",
secret: "<clientSecret>",
})
const result = await reddit.getSubreddit({
sortMethod: SortingMethod.Hot,
name: "memes",
fields: ["title", "url"],
})
In the above example, I picked only the fields that I needed, here is the response:
{
before: null,
after: 't3_1aihq82',
data: [
{
title: 'r/Memes is looking for new moderators! Interested? Fill out our application!',
url: 'https://docs.google.com/forms/d/e/1FAIpQLSfBlrL6LVOktwIdGubvbJ7REeh9vANiBTIpUecW63PHINQECg/viewform'
},
{
title: 'Worst days in University',
url: 'https://i.redd.it/u8hlua9lbkgc1.jpeg'
},
// some other results...
],
}
SubredditData
typeThis type offers the possibility to handle the response more easily (response.children[0]
):
export type SubredditData = {
approved_at_utc: any
subreddit: string
selftext: string
author_fullname: string
saved: boolean
mod_reason_title: any
gilded: number
clicked: boolean
title: string
link_flair_richtext: any[]
subreddit_name_prefixed: string
hidden: boolean
pwls: number
link_flair_css_class: any
downs: number
thumbnail_height: number
top_awarded_type: any
hide_score: boolean
name: string
quarantine: boolean
link_flair_text_color: string
upvote_ratio: number
author_flair_background_color: any
subreddit_type: string
ups: number
total_awards_received: number
media_embed: null | {
content: IFrame
width: number
scrolling: boolean
height: number
}
thumbnail_width: number
author_flair_template_id: any
is_original_content: boolean
user_reports: any[]
secure_media: null | {
type: string
oembed: {
provider_url: string
version: string
title: string
type: string
thumbnail_width: number
height: number
width: number
html: IFrame
author_name: string
provider_name: string
thumbnail_url: string
thumbnail_height: number
author_url: string
}
}
is_reddit_media_domain: boolean
is_meta: boolean
category: any
secure_media_embed: null | {
content: IFrame
width: number
scrolling: boolean
media_domain_url: Url
height: number
}
link_flair_text: string
can_mod_post: boolean
score: number
approved_by: any
is_created_from_ads_ui: boolean
author_premium: boolean
thumbnail: Url
edited: boolean
author_flair_css_class: any
author_flair_richtext: any[]
gildings: {
gid_1: number
}
post_hint: string
content_categories: any
is_self: boolean
mod_note: any
crosspost_parent_list?: SubredditData[]
created: number
link_flair_type: string
wls: number
removed_by_category: any
banned_by: any
author_flair_type: string
domain: Url
allow_live_comments: boolean
selftext_html: any
likes: any
suggested_sort: any
banned_at_utc: any
url_overridden_by_dest: Url
view_count: any
archived: boolean
no_follow: boolean
is_crosspostable: boolean
pinned: boolean
over_18: boolean
preview: {
images: [
{
source: {
url: Url
width: number
height: number
}
resolutions: {
url: Url
width: number
height: number
}[]
variants: {
obfuscated: {
source: {
url: Url
width: number
height: number
}
resolutions: {
url: Url
width: number
height: number
}[]
}
nsfw: {
source: {
url: Url
width: number
height: number
}
resolutions: {
url: Url
width: number
height: number
}[]
}
}
id: string
}
]
reddit_video_preview: {
bitrate_kbps: number
fallback_url: string
height: number
width: number
scrubber_media_url: string
dash_url: string
duration: number
hls_url: string
is_gif: boolean
transcoding_status: string
}
enabled: boolean
}
all_awardings: any[]
awarders: any[]
media_only: boolean
can_gild: boolean
spoiler: boolean
locked: boolean
author_flair_text: null
treatment_tags: []
visited: boolean
removed_by: null
num_reports: null
distinguished: null
subreddit_id: string
mod_reason_by: null
removal_reason: null
link_flair_background_color: string
id: string
is_robot_indexable: boolean
report_reasons: null
author: string
discussion_type: null
num_comments: number
send_replies: boolean
whitelist_status: string
contest_mode: boolean
mod_reports: []
author_patreon_flair: boolean
crosspost_parent?: string
author_flair_text_color: null
permalink: string
parent_whitelist_status: string
stickied: boolean
url: Url
subreddit_subscribers: number
created_utc: number
num_crossposts: number
media: null | {
type: string
oembed: {
provider_url: Url
version: string
title: string
type: string
thumbnail_width: number
height: number
width: number
html: IFrame
author_name: string
provider_name: string
thumbnail_url: Url
thumbnail_height: number
author_url: Url
}
}
is_video: boolean
sr_detail: {
default_set: boolean
banner_img: string
restrict_posting: boolean
user_is_banned?: any
free_form_reports: boolean
community_icon?: any
show_media: boolean
description: string
user_is_muted?: any
display_name: string
header_img: string
title: string
previous_names: any[]
user_is_moderator?: any
over_18: boolean
icon_size: number[]
primary_color: string
icon_img: string
icon_color: string
submit_link_label: string
header_size: number[]
restrict_commenting: boolean
subscribers: number
submit_text_label: string
link_flair_position: string
display_name_prefixed: string
key_color: string
name: string
created: number
url: string
quarantine: boolean
created_utc: number
banner_size: number[]
user_is_contributor?: any
accept_followers: boolean
public_description: string
link_flair_enabled: boolean
disable_contributor_requests: boolean
subreddit_type: string
user_is_subscriber?: any
}
}
Here you'll find the official documentation of the reddit official endpoints that this package uses:
FAQs
Simple reddit client that allows to fetch reddit names and content from any subreddit, without any account authentication.
We found that reddit-explorer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.