Version: v0.0.0-...-a177df1 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Dec 4, 2020 License: MIT Imports: 15 Imported by: 29



Package reddit is a small wrapper around the Reddit API.

It provides two handles for the Reddit API. Logged out users can claim a Script handle.

rate := 5 * time.Second
script, _ := NewScript("graw:doc_script:0.3.1 by /u/yourusername", rate)
post, _ := script.Thread("r/programming/comments/5du93939")
fmt.Printf("%s posted \"%s\"!", post.Author, post.Title)

Logged in users can claim a Bot handle with a superset of the former's features.

cfg := BotConfig{
  Agent: "graw:doc_demo_bot:0.3.1 by /u/yourusername"
  // Your registered app info from following:
  App: App{
    ID:     "sdf09ofnsdf",
    Secret: "skldjnfksjdnf",
    Username: "yourbotusername",
    Password: "yourbotspassword",
bot, _ := NewBot(cfg)
bot.SendMessage("roxven", "Thanks for making this Reddit API!", "It's ok.")

Requests made by this API are rate limited with no bursting. All interfaces exported by this package have goroutine safe implementations, but when shared by many goroutines some calls may block for multiples of the rate limit interval.

This API for accessing feeds from Reddit is low level, built specifically for graw. If you are interested in a simple high level event feed, see graw.



This section is empty.


View Source
var (
	PermissionDeniedErr   = fmt.Errorf("unauthorized access to endpoint")
	BusyErr               = fmt.Errorf("Reddit is busy right now")
	RateLimitErr          = fmt.Errorf("Reddit is rate limiting requests")
	GatewayErr            = fmt.Errorf("502 bad gateway code from Reddit")
	GatewayTimeoutErr     = fmt.Errorf("504 gateway timeout from Reddit")
	ThreadDoesNotExistErr = fmt.Errorf("The requested post does not exist.")


This section is empty.


type Account

type Account interface {
	// Reply posts a reply to something on reddit. The behavior depends on
	// what is being replied to. For
	//   messages, this sends a private message reply.
	//   posts, this posts a top level comment.
	//   comments, this posts a comment reply.
	// Use .Name on the parent post, message, or comment to find its
	// name.
	Reply(parentName, text string) error
	GetReply(parentName, text string) (Submission, error)

	// SendMessage sends a private message to a user.
	SendMessage(user, subject, text string) error

	// PostSelf makes a text (self) post to a subreddit.
	PostSelf(subreddit, title, text string) error
	GetPostSelf(subreddit, title, text string) (Submission, error)

	// PostLink makes a link post to a subreddit.
	PostLink(subreddit, title, url string) error
	GetPostLink(subreddit, title, url string) (Submission, error)

Account defines behaviors only an account can perform on Reddit.

type App

type App struct {
	// ID and Secret are used to claim an OAuth2 grant the bot's account
	// previously authorized.
	ID     string
	Secret string

	// Username and Password are used to authorize with the endpoint.
	Username string
	Password string
	// contains filtered or unexported fields

App holds all the information needed to identify as a registered app on Reddit. If you are unfamiliar with this information, you can find it in your "apps" tab on reddit; see this tutorial:

type Bot

type Bot interface {

Bot defines the behaviors of a logged in Reddit bot.

func NewBot

func NewBot(c BotConfig) (Bot, error)

NewBot returns a logged in handle to the Reddit API.

func NewBotFromAgentFile

func NewBotFromAgentFile(filename string, rate time.Duration) (Bot, error)

NewBotFromAgentFile calls NewBot with a config built from an agent file. An agent file is a convenient way to store your bot's account information. See

type BotConfig

type BotConfig struct {
	// Agent is the user-agent sent in all requests the bot makes through
	// this package.
	Agent string
	// App is the information for your registration on Reddit.
	// If you are not familiar with this, read:
	App App
	// Rate is the minimum amount of time between requests. If Rate is
	// configured lower than 1 second, the it will be ignored; Reddit's API
	// rules cap OAuth2 clients at 60 requests per minute. See package
	// overview for rate limit information.
	Rate time.Duration
	// Custom HTTP client
	Client *http.Client

BotConfig configures a Reddit bot's behavior with the Reddit package.

type Comment

type Comment struct {
	ID        string `mapstructure:"id"`
	Name      string `mapstructure:"name"`
	Permalink string `mapstructure:"permalink"`

	CreatedUTC uint64 `mapstructure:"created_utc"`
	Edited     uint64 `mapstructure:"edited"`
	Deleted    bool   `mapstructure:"deleted"`

	Ups   int32 `mapstructure:"ups"`
	Downs int32 `mapstructure:"downs"`
	Likes bool  `mapstructure:"likes"`

	Author              string `mapstructure:"author"`
	AuthorFlairCSSClass string `mapstructure:"author_flair_css_class"`
	AuthorFlairText     string `mapstructure:"author_flair_text"`

	LinkAuthor string `mapstructure:"link_author"`
	LinkURL    string `mapstructure:"link_url"`
	LinkTitle  string `mapstructure:"link_title"`

	Subreddit   string `mapstructure:"subreddit"`
	SubredditID string `mapstructure:"subreddit_id"`

	Body     string `mapstructure:"body"`
	BodyHTML string `mapstructure:"body_html"`

	ParentID string     `mapstructure:"parent_id"`
	Replies  []*Comment `mapstructure:"reply_tree"`
	More     *More

	Gilded        int32  `mapstructure:"gilded"`
	Distinguished string `mapstructure:"distinguished"`

Comment represents a comment on Reddit (Reddit type t1_).

func (*Comment) IsTopLevel

func (c *Comment) IsTopLevel() bool

IsTopLevel is true when the comment is a top level comment.

type Harvest

type Harvest struct {
	Comments []*Comment
	Posts    []*Post
	Messages []*Message
	Mores    []*More

Harvest is a set of all possible elements that Reddit could return in a listing.

Typically the items returned in this harvest are flat. You will not find the comment tree for each post in their `Replies` field. This is because that can be a lot of data. If you want a full comment tree, use the `Thread` method on the bot with the post's `Permalink`.

type Lurker

type Lurker interface {
	// Thread returns a Reddit post with a fully parsed comment tree.
	Thread(permalink string) (*Post, error)

Lurker defines browsing behavior.

type Media

type Media struct {
	Type   string `mapstructure:"type"`
	OEmbed struct {
		ProviderURL     string `mapstructure:"provider_url"`
		Description     string `mapstructure:"description"`
		Title           string `mapstructure:"title"`
		ThumbnailWidth  int    `mapstructure:"thumbnail_width"`
		Height          int    `mapstructure:"height"`
		Width           int    `mapstructure:"width"`
		HTML            string `mapstructure:"html"`
		Version         string `mapstructure:"version"`
		ProviderName    string `mapstructure:"provider_name"`
		ThumbnailURL    string `mapstructure:"thumbnail_url"`
		Type            string `mapstructure:"type"`
		ThumbnailHeight int    `mapstructure:"thumbnail_height"`
	} `mapstructure:"oembed"`
	RedditVideo struct {
		FallbackURL       string `mapstructure:"fallback_url"`
		Height            int    `mapstructure:"height"`
		Width             int    `mapstructure:"width"`
		ScrubberMediaURL  string `mapstructure:"scrubber_media_url"`
		DashURL           string `mapstructure:"dash_url"`
		Duration          int    `mapstructure:"duration"`
		HLSURL            string `mapstructure:"hls_url"`
		IsGIF             bool   `mapstructure:"is_gif"`
		TranscodingStatus string `mapstructure:"transcoding_status"`
	} `mapstructure:"reddit_video"`

Media represents a subfield in the response about posts

type Message

type Message struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`

	CreatedUTC uint64 `mapstructure:"created_utc"`

	Author   string `mapstructure:"author"`
	Subject  string `mapstructure:"subject"`
	Body     string `mapstructure:"body"`
	BodyHTML string `mapstructure:"body_html"`

	Context          string `mapstructure:"context"`
	FirstMessageName string `mapstructure:"first_message_name"`
	Likes            bool   `mapstructure:"likes"`
	LinkTitle        string `mapstructure:"link_title"`

	New      bool   `mapstructure:"new"`
	ParentID string `mapstructure:"parent_id"`

	Subreddit  string `mapstructure:"subreddit"`
	WasComment bool   `mapstructure:"was_comment"`

Message represents messages on Reddit (Reddit type t4_).

type More

type More struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`

	Count    int    `mapstructure:"count"`
	Depth    int    `mapstructure:"depth"`
	ParentID string `mapstructure:"parent_id"`

	Children []string `mapstructure:"children"`

More represents a more comments list on Reddit

type Post

type Post struct {
	ID        string `mapstructure:"id"`
	Name      string `mapstructure:"name"`
	Permalink string `mapstructure:"permalink"`

	CreatedUTC uint64 `mapstructure:"created_utc"`
	Deleted    bool   `mapstructure:"deleted"`

	Ups   int32 `mapstructure:"ups"`
	Downs int32 `mapstructure:"downs"`
	Likes bool  `mapstructure:"likes"`

	Author              string `mapstructure:"author"`
	AuthorFlairCSSClass string `mapstructure:"author_flair_css_class"`
	AuthorFlairText     string `mapstructure:"author_flair_text"`

	Title  string `mapstructure:"title"`
	Score  int32  `mapstructure:"score"`
	URL    string `mapstructure:"url"`
	Domain string `mapstructure:"domain"`
	NSFW   bool   `mapstructure:"over_18"`

	Subreddit   string `mapstructure:"subreddit"`
	SubredditID string `mapstructure:"subreddit_id"`

	IsSelf       bool   `mapstructure:"is_self"`
	SelfText     string `mapstructure:"selftext"`
	SelfTextHTML string `mapstructure:"selftext_html"`

	Replies []*Comment `mapstructure:"reply_tree"`
	More    *More

	Hidden            bool   `mapstructure:"hidden"`
	LinkFlairCSSClass string `mapstructure:"link_flair_css_class"`
	LinkFlairText     string `mapstructure:"link_flair_text"`

	NumComments int32  `mapstructure:"num_comments"`
	Locked      bool   `mapstructure:"locked"`
	Thumbnail   string `mapstructure:"thumbnail"`

	Gilded        int32  `mapstructure:"gilded"`
	Distinguished string `mapstructure:"distinguished"`
	Stickied      bool   `mapstructure:"stickied"`

	IsRedditMediaDomain bool  `mapstructure:"is_reddit_media_domain"`
	Media               Media `mapstructure:"media"`
	SecureMedia         Media `mapstructure:"secure_media"`

Post represents posts on Reddit (Reddit type t3_).

type Scanner

type Scanner interface {
	// Listing returns a harvest from a listing endpoint at Reddit.
	// There are many things to consider when using this. A listing on
	// Reddit is like an infinite, unstable list. It stretches functionally
	// infinitely forward and backward in time, and elements from it vanish
	// over time for many reasons (users delete their posts, posts get
	// caught in a spam filter, mods remove them, etc).
	// The "after" parameter is the name (in the form tx_xxxxxx, found by
	// the Name field of any Reddit struct defined in this package) of an
	// element known to be in the list. If an empty string the latest 100
	// elements are returned.
	// The way to subscribe to a listing is continually poll this, and keep
	// track of your reference point, and replace it if it gets deleted or
	// dropped from the listing for any reason, which is nontrivial. If your
	// reference point becomes invalid, you will get no elements in the
	// harvest and have no way to find your place unless you planned ahead.
	// If you want a stream where all of this is handled for you, see graw
	// or graw/streams.
	Listing(path, after string) (Harvest, error)
	ListingWithParams(path string, params map[string]string) (Harvest, error)

Scanner defines a low level interface for fetching reading Reddit listings.

type Script

type Script interface {

Script defines the behaviors of a logged out Reddit script.

func NewScript

func NewScript(agent string, rate time.Duration) (Script, error)

NewScript returns a Script handle to Reddit's API which always sends the given agent in the user-agent header of its requests and makes requests with no less time between them than rate. The minimum respected value of rate is 2 seconds, because Reddit's API rules cap logged out non-OAuth clients at 30 requests per minute.

func NewScriptFromConfig

func NewScriptFromConfig(config ScriptConfig) (Script, error)

NewScriptFromConfig returns a Script handle to Reddit's API from ScriptConfig

type ScriptConfig

type ScriptConfig struct {
	// Agent is the user-agent sent in all requests the bot makes through
	// this package.
	Agent string
	// Rate is the minimum amount of time between requests.
	Rate time.Duration
	// Custom HTTP client
	Client *http.Client

type Submission

type Submission struct {
	ID   string `mapstructure:"id"`
	Name string `mapstructure:"name"`
	URL  string `mapstructure:"url"`

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL