Documentation
¶
Overview ¶
Package mira or Meme Investor Reddit API
Fork by ttgmpsn. For the original project by @thecsw, please see https://github.com/thecsw/mira/.
Type Prefixes ¶
Reddit IDs are in the form of PREFIX_ID, with ID being in base36. A post ID for example looks like t3_aaaaa. This is the current table of prefixes:
| Prefix | Type | |--------|----------------------------------| | t1 | Comment | | t2 | Redditor | | t3 | Submission, PostListing contents | | t4 | Message | | t5 | Subreddit | | t6 | Award |
Index ¶
- Constants
- type Credentials
- type Interface
- type NotifyRefreshTokenSource
- type Reddit
- func (c *Reddit) Approve() error
- func (c *Reddit) AuthCodeURL(state string, scopes []string) string
- func (c *Reddit) Ban(redditor string, days int, context, message, reason string) error
- func (c *Reddit) CodeAuth(code string, f TokenNotifyFunc) error
- func (c *Reddit) Comment(name string) *Reddit
- func (c *Reddit) Comments(sort string, tdur string, limit int) ([]*models.Comment, error)
- func (c *Reddit) CommentsAfter(sort string, last models.RedditID, limit int) ([]*models.Comment, error)
- func (c *Reddit) Compose(subject, text string) error
- func (c *Reddit) Delete() error
- func (c *Reddit) Distinguish(how string, sticky bool) error
- func (c *Reddit) Edit(text string) (*models.Comment, error)
- func (c *Reddit) EditWiki(page, content, reason string) error
- func (c *Reddit) GetModMailByID(conversationID string, markRead bool) (*models.NewModmailConversation, error)
- func (c *Reddit) GetParentPost() (models.RedditID, error)
- func (c *Reddit) Info() (models.RedditThing, error)
- func (c *Reddit) ListUnreadMessages() ([]*models.Comment, error)
- func (c *Reddit) LoginAuth() error
- func (c *Reddit) Me() *Reddit
- func (c *Reddit) MiraRequest(method string, target string, payload map[string]string) ([]byte, error)
- func (c *Reddit) ModLog(limit int, mod string) ([]*models.ModAction, error)
- func (c *Reddit) ModQueue(limit int) ([]models.Submission, error)
- func (c *Reddit) Post(name string) *Reddit
- func (c *Reddit) Posts(sort string, tdur string, limit int) ([]*models.Post, error)
- func (c *Reddit) PostsAfter(last models.RedditID, limit int) ([]*models.Post, error)
- func (c *Reddit) ReadAllMessages() error
- func (c *Reddit) ReadMessage(messageID string) error
- func (c *Reddit) Redditor(name string) *Reddit
- func (c *Reddit) Remove(spam bool) error
- func (c *Reddit) Reply(text string) (*models.CommentActionResponse, error)
- func (c *Reddit) ReplyWithID(name, text string) (*models.CommentActionResponse, error)
- func (c *Reddit) SelectFlair(text string) error
- func (c *Reddit) SetDefault()
- func (c *Reddit) SetToken(t *oauth2.Token, scopes []string, f TokenNotifyFunc) error
- func (c *Reddit) StreamComments() (*SubmissionStream, error)
- func (c *Reddit) StreamPosts() (*SubmissionStream, error)
- func (c *Reddit) Stylesheet() (*models.Stylesheet, error)
- func (c *Reddit) SubmissionInfo() (models.Submission, error)
- func (c *Reddit) SubmissionInfoID(name models.RedditID) (models.Submission, error)
- func (c *Reddit) Submissions(limit int) ([]models.Submission, error)
- func (c *Reddit) SubmissionsAfter(last models.RedditID, limit int) ([]models.Submission, error)
- func (c *Reddit) Submit(title string, text string) (*models.PostActionResponse, error)
- func (c *Reddit) Subreddit(name ...string) *Reddit
- func (c *Reddit) UpdateSidebar(text string) error
- func (c *Reddit) UserFlair(user, text string) error
- func (c *Reddit) Wiki(page string) (*models.Wiki, error)
- type RedditErr
- type SubmissionStream
- type TokenNotifyFunc
Examples ¶
Constants ¶
const ( RedditBase = "https://www.reddit.com/" RedditOauth = "https://oauth.reddit.com" )
RedditBase is the basic reddit URL, RedditOauth is the base URL for use once authenticated
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Credentials ¶
type Credentials struct { ClientID string ClientSecret string Username string Password string UserAgent string RedirectURL string }
Credentials stores information for authing towards the Reddit API. You can create an app here: https://old.reddit.com/prefs/apps/
type Interface ¶
type Interface interface { GetID() string GetParentID() string GetTitle() string GetBody() string GetAuthor() string GetName() string GetKarma() float64 GetUps() float64 GetDowns() float64 GetSubreddit() string GetCreated() float64 GetFlair() string GetURL() string IsRoot() bool }
Interface can be used for any reddit object (Post, Comment, etc.) to avoid type hinting.
type NotifyRefreshTokenSource ¶
type NotifyRefreshTokenSource struct {
// contains filtered or unexported fields
}
NotifyRefreshTokenSource is essentially oauth2.ResuseTokenSource with TokenNotifyFunc added.
type Reddit ¶
type Reddit struct { Client *http.Client OAuthConfig *oauth2.Config TokenExpiry time.Time UserAgent string Chain chan *chainVals Values redditVals // contains filtered or unexported fields }
Reddit holds the connection to the API for a user. You can have multiple Reddit instances at the same time (see Example below).
Calling Methods ¶
Each method is called similarly: First, you queue an object (Subreddit, Comment, Redditor etc) you want to perform the action on. Afterwards (this can be done in the same call), you select the command:
reddit.Subreddit("iama").Submit("I just did a bot, AMA", "Hey all! I just created a bot. AMA.") reddit.Redditor("spez").Compose("Hi spez!", "Hi spez how are you?")
Working with submissions ¶
If you call a function that returns a post or comment, you will receive an object that confirms to the models.Submission interface. You should be able to get most of the values without type hinting with the functions provided in the interface:
submission = reddit.SubmissionInfoID("t3_aaaaa") fmt.Println("Got a post with body:", post.GetBody())
If you need detailed information, you can do a type assertion:
post, _ := submission.(*miramodels.Post) fmt.Println("Post Flair Text:", post.LinkFlairText)
Example ¶
If you have multiple users in parallel, you can initialize multiple reddit objects to switch between them:
package main import ( "github.com/ttgmpsn/mira" ) func main() { redditInstances := make(map[string]*mira.Reddit) // Login as users - heavily shortened, see CodeAuth / LoginAuth examples: // User 1: ttgmpsn reddit1 := mira.Init(mira.Credentials{}) reddit1.CodeAuth("", nil) redditInstances["ttgmpsn"] = reddit1 // User 2: ttgmbot reddit2 := mira.Init(mira.Credentials{}) reddit2.CodeAuth("", nil) redditInstances["ttgmbot"] = reddit2 // If redditInstances is a global variable, you can now use it everywhere! }
Output:
func Init ¶
func Init(c Credentials) *Reddit
Init will initialize the Reddit instance. Note that you most likely want to auth using LoginAuth() or CodeAuth() afterwards, see the examples there.
func (*Reddit) AuthCodeURL ¶
AuthCodeURL creates and returns an auth URL which contains an auth code.
func (*Reddit) CodeAuth ¶
func (c *Reddit) CodeAuth(code string, f TokenNotifyFunc) error
CodeAuth creates and sets a token using an authentication code returned from AuthCodeURL. Note that Username & Password provided to Init are ignored. You can optionally pass a TokenNotifyFunc to get notified when the token changes (i.e. to store it into a database). Pass nil if you do not want to use this.
Example ¶
package main import ( "fmt" "github.com/ttgmpsn/mira" miramodels "github.com/ttgmpsn/mira/models" ) func main() { reddit := mira.Init(mira.Credentials{ ClientID: "clientid", ClientSecret: "clientsecret", UserAgent: "MIRA CodeAuth Example v0", RedirectURL: "https://example.com/auth", // This must be equal to the value you set in the reddit app config, or you will get an error! }) // Provide all scopes you need to OAuthConfig reddit.OAuthConfig.Scopes = []string{"identity", "submit"} // Step 1: Generate URL to redirect user to: // The state is a unique value you can use to distinguish between user requests. It won't be used by reddit, just returned to your app later (see below). state := "UniqueStateToDistinguish" // AuthURL is a link to reddit.com, where a user has to confirm the scopes you request, and can choose to accept/decline the auth request. AuthURL := reddit.AuthCodeURL(state, reddit.OAuthConfig.Scopes) fmt.Printf("Visit this URL to continue the Authentication Flow: %s\n", AuthURL) // Step 2: If a user approves your app, he will be redirected to your RedirectURL. // In this example, the request would look like https://example.com/auth?state=UniqueStateToDistinguish&code=TOPSECRETCODE // With the code, you can then continue with Step 2 of the authentication flow: Actually getting your access token. // The code below usually is in a separate function that handles the "auth" endpoint. Just re-initialize "reddit" like above. code := "TOPSECRETCODE" // usually would be sth. like r.URL.Query()["code"] if err := reddit.CodeAuth(code, nil); err != nil { panic(err) } // Done! You can now use reddit authenticated as that user & can use reddit: rMeObj, err := reddit.Me().Info() if err != nil { panic(err) } rMe, _ := rMeObj.(*miramodels.Me) fmt.Printf("You are now logged in, /u/%s\n", rMe.Name) // Note that the access token cannot be retreived separately. This is by design, since it is useless after a few hours. // Instead, you should use a TokenNotifyFunc. See example there. }
Output:
Example (ResumingSession) ¶
Assumung you have saved the Refresh Token (see example for TokenNotifyFunc), this is how you can restore a session using it:
package main import ( "fmt" "time" "github.com/ttgmpsn/mira" miramodels "github.com/ttgmpsn/mira/models" "golang.org/x/oauth2" ) func main() { handleRefreshToken := func(t *oauth2.Token) error { // See TokenNotifyFunc example return nil } reddit := mira.Init(mira.Credentials{ ClientID: "clientid", ClientSecret: "clientsecret", UserAgent: "MIRA CodeAuth Example v0", RedirectURL: "https://example.com/auth", // This must be equal to the value you set in the reddit app config, or you will get an error! }) reddit.OAuthConfig.Scopes = []string{"identity", "submit"} refreshToken := "secret" // fetched from database or similar reddit.SetToken(&oauth2.Token{ AccessToken: "VOID", RefreshToken: refreshToken, Expiry: time.Now().Add(time.Minute * -1), // Set the Access Token to expire immediately so a new one is fetched }, reddit.OAuthConfig.Scopes, handleRefreshToken) // Done! You can now use reddit authenticated as that user & can use reddit: rMeObj, err := reddit.Me().Info() if err != nil { panic(err) } rMe, _ := rMeObj.(*miramodels.Me) fmt.Printf("You are now logged in again, /u/%s\n", rMe.Name) }
Output:
func (*Reddit) Comments ¶
Comments gets comments for the last queued object. Valid objects: Subreddit, Post, Redditor
func (*Reddit) CommentsAfter ¶
func (c *Reddit) CommentsAfter(sort string, last models.RedditID, limit int) ([]*models.Comment, error)
CommentsAfter gets comments for the last queued object after a given item. Valid objects: Subreddit, Redditor
func (*Reddit) Compose ¶
Compose writes a private message to the last queued object. Valid objects: Redditor
func (*Reddit) Distinguish ¶
Distinguish the last queued object. Valid objects: Comment
func (*Reddit) EditWiki ¶ added in v0.1.11
EditWiki edits/creates a wiki page from last queued object. Valid objects: Subreddit
func (*Reddit) GetModMailByID ¶ added in v0.1.1
func (c *Reddit) GetModMailByID(conversationID string, markRead bool) (*models.NewModmailConversation, error)
GetModMailByID returns the ModMail Conversation for a given modmail ID
func (*Reddit) GetParentPost ¶
GetParentPost returns the Post ID for the last queued object. Valid objects: Comment
func (*Reddit) Info ¶
func (c *Reddit) Info() (models.RedditThing, error)
Info returns general information about the queued object as a mira.Interface.
func (*Reddit) ListUnreadMessages ¶
ListUnreadMessages for the last queued object. Valid objects: Me
func (*Reddit) LoginAuth ¶
LoginAuth creates the required HTTP client with a new token. Creds are taken from the data provided to Init. Tokens are refreshed automatically shortly before the session runs out.
Example ¶
package main import ( "fmt" "github.com/ttgmpsn/mira" miramodels "github.com/ttgmpsn/mira/models" ) func main() { reddit := mira.Init(mira.Credentials{ ClientID: "clientid", ClientSecret: "clientsecret", Username: "reddit_username", Password: "topsecretpassword", UserAgent: "MIRA LoginAuth Example v0", }) err := reddit.LoginAuth() if err != nil { panic(err) } // You can now use reddit as an authenticated user: rMeObj, err := reddit.Me().Info() if err != nil { panic(err) } rMe, _ := rMeObj.(*miramodels.Me) fmt.Printf("You are now logged in, /u/%s\n", rMe.Name) }
Output:
func (*Reddit) MiraRequest ¶
func (c *Reddit) MiraRequest(method string, target string, payload map[string]string) ([]byte, error)
MiraRequest can be used to make custom requests to the reddit API.
func (*Reddit) ModLog ¶
ModLog returns the mod log from the last queued object. Valid objects: Subreddit
func (*Reddit) ModQueue ¶
func (c *Reddit) ModQueue(limit int) ([]models.Submission, error)
ModQueue returns the mod queue from the last queued object. Valid objects: Subreddit
func (*Reddit) Posts ¶
Posts gets posts for the last queued object. Valid objects: Subreddit, Redditor
func (*Reddit) PostsAfter ¶
PostsAfter gets posts for the last queued object after a given item. Valid objects: Subreddit, Redditor
func (*Reddit) ReadAllMessages ¶
ReadAllMessages marks all message for the last queued object as read. Valid objects: Me
func (*Reddit) ReadMessage ¶
ReadMessage marks a message for the last queued object as read. Valid objects: Me
func (*Reddit) Remove ¶
Remove mod-removes the last queued object. To remove own comments, please use Delete() Valid objects: Comment, Post
func (*Reddit) Reply ¶
func (c *Reddit) Reply(text string) (*models.CommentActionResponse, error)
Reply adds a comment to the last queued object. Valid objects: Comment, Post
func (*Reddit) ReplyWithID ¶
func (c *Reddit) ReplyWithID(name, text string) (*models.CommentActionResponse, error)
ReplyWithID adds a comment to the given thing id, without it needing to be queued up.
func (*Reddit) SelectFlair ¶
SelectFlair for the last queued object. Valid objects: Post
func (*Reddit) SetDefault ¶
func (c *Reddit) SetDefault()
SetDefault gets sensible default values for streams.
func (*Reddit) SetToken ¶
SetToken manually assigns a token to the Reddit object. This is useful if you have your token information saved from a prior run. You can optionally pass a TokenNotifyFunc to get notified when the token changes (i.e. to store it into a database). Pass nil if you do not want to use this.
func (*Reddit) StreamComments ¶ added in v0.1.5
func (c *Reddit) StreamComments() (*SubmissionStream, error)
StreamComments streams comments for the last queued object. Valid objects: Subreddit, (Redditor)
func (*Reddit) StreamPosts ¶ added in v0.1.5
func (c *Reddit) StreamPosts() (*SubmissionStream, error)
StreamPosts streams posts for the last queued object. Valid objects: Subreddit, (Redditor)
Example ¶
package main import ( "fmt" "github.com/ttgmpsn/mira" miramodels "github.com/ttgmpsn/mira/models" ) func main() { // Initialize reddit instance like usually - see other examples. reddit := mira.Init(mira.Credentials{}) // Create stream stream, err := reddit.Subreddit("pics").StreamPosts() if err != nil { panic(err) } // Create listener go func() { var s miramodels.Submission for s = range stream.C { if s == nil { fmt.Println("Stream was closed") return } fmt.Println("Received new item in stream:", s.GetID()) } }() }
Output:
func (*Reddit) Stylesheet ¶ added in v0.1.10
func (c *Reddit) Stylesheet() (*models.Stylesheet, error)
Stylesheet returns the stylesheet & images from last queued object. Valid objects: Subreddit
func (*Reddit) SubmissionInfo ¶
func (c *Reddit) SubmissionInfo() (models.Submission, error)
SubmissionInfo returns general information about the queued submission.
func (*Reddit) SubmissionInfoID ¶
SubmissionInfoID returns general information about the submission ID.
func (*Reddit) Submissions ¶ added in v0.1.7
func (c *Reddit) Submissions(limit int) ([]models.Submission, error)
Submissions gets submissions for the last queued object. Valid objects: Redditor
func (*Reddit) SubmissionsAfter ¶ added in v0.1.7
SubmissionsAfter gets submissions for the last queued object after a given item. Valid objects: Redditor
func (*Reddit) Submit ¶
Submit submits a new Post to the last queued object. Valid objects: Subreddit
func (*Reddit) Subreddit ¶
Subreddit queues up the next action to be about one or multuple Subreddits.
func (*Reddit) UpdateSidebar ¶
UpdateSidebar of the last queued object. Valid objects: Subreddit
type SubmissionStream ¶ added in v0.1.5
type SubmissionStream struct { C <-chan models.Submission Close chan struct{} }
SubmissionStream has two objects: a channel "C" where you can receive Submissions (posts or comments), and a channel "close" - close that channel to stop receiving events. Please use the close channel appropriately or you'll be polling reddit non-stop!
type TokenNotifyFunc ¶
TokenNotifyFunc is a function that accepts an oauth2 Token upon refresh, and returns an error if it should not be used. Use this to cache Refresh Token if you want to (you'll most likely want to). Taken from https://github.com/golang/oauth2/issues/84#issuecomment-332517319
Example ¶
This example assumes you have read and understand the CodeAuth() example.
To save the refresh token & grab a new access token once it expires, you can use a notify function that will be called each time the token is refreshed (which happens automatically while your app is running)
package main import ( "fmt" "github.com/ttgmpsn/mira" "golang.org/x/oauth2" ) func main() { reddit := mira.Init(mira.Credentials{ ClientID: "clientid", ClientSecret: "clientsecret", UserAgent: "MIRA TokenNotifyFunc Example v0", RedirectURL: "https://example.com/auth", }) reddit.OAuthConfig.Scopes = []string{"identity", "submit"} // handleRefreshToken statifies the mira.TokenNotifyFunc interface handleRefreshToken := func(t *oauth2.Token) error { fmt.Println("Refreshed Token:") fmt.Println("- New Access Token:", t.AccessToken) fmt.Println("- New Refresh Token:", t.RefreshToken) // Probably save to Database or similar. return nil } // Step 1 is similar to the CodeAuth example. See there. // Step 2 changes slightly. For extended documentation please see the CodeAuth example. code := "TOPSECRETCODE" // usually would be sth. like r.URL.Query()["code"] if err := reddit.CodeAuth(code, handleRefreshToken); err != nil { panic(err) } // This is it! Each time the token will be refreshed (which happens automatically), handleRefreshToken() will be called with the latest information. // If you have multiple users, you should probably add something to distinguish between them :) }
Output: