Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add oauth funcs for getting post by id, comment by id, posts by user, comments by user #55

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# geddit

[![GoDoc](https://godoc.org/github.com/jzelinskie/geddit?status.svg)](https://godoc.org/github.com/jzelinskie/geddit)
[![Go Report Card](https://goreportcard.com/badge/github.com/jzelinskie/geddit)](https://goreportcard.com/report/github.com/jzelinskie/geddit)
[![GoDoc](https://godoc.org/github.com/khipkin/geddit?status.svg)](https://godoc.org/github.com/khipkin/geddit)
[![Go Report Card](https://goreportcard.com/badge/github.com/khipkin/geddit)](https://goreportcard.com/report/github.com/khipkin/geddit)
[![Build Status](https://api.travis-ci.org/jzelinskie/geddit.svg?branch=master)](https://travis-ci.org/jzelinskie/geddit)

Geddit is a convenient abstraction for the [reddit.com](http://reddit.com) API in Go.
Expand All @@ -10,7 +10,7 @@ It should have some API coverage, but does not yet include things like the new O

## examples

See [godoc](http://godoc.org/github.com/jzelinskie/geddit) for OAuth examples.
See [godoc](http://godoc.org/github.com/khipkin/geddit) for OAuth examples.

Here is an example usage of the old, cookie authentication method:

Expand All @@ -22,7 +22,7 @@ package main
import (
"fmt"

"github.com/jzelinskie/geddit"
"github.com/khipkin/geddit"
)

// Please don't handle errors this way.
Expand Down
55 changes: 34 additions & 21 deletions comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ import (

// Comment represents a reddit comment.
type Comment struct {
Author string //`json:"author"`
Body string //`json:"body"`
BodyHTML string //`json:"body_html"`
Subreddit string //`json:"subreddit"`
LinkID string //`json:"link_id"`
ParentID string //`json:"parent_id"`
SubredditID string //`json:"subreddit_id"`
FullID string //`json:"name"`
Permalink string //`json:"permalink"`
Score float64 //`json:"score"`
UpVotes float64 //`json:"ups"`
DownVotes float64 //`json:"downs"`
Created float64 //`json:"created_utc"`
Edited bool //`json:"edited"`
BannedBy *string //`json:"banned_by"`
ApprovedBy *string //`json:"approved_by"`
AuthorFlairTxt *string //`json:"author_flair_text"`
AuthorFlairCSSClass *string //`json:"author_flair_css_class"`
NumReports *int //`json:"num_reports"`
Likes *int //`json:"likes"`
Author string `json:"author"`
Body string `json:"body"`
BodyHTML string `json:"body_html"`
Subreddit string `json:"subreddit"`
LinkID string `json:"link_id"`
ParentID string `json:"parent_id"`
SubredditID string `json:"subreddit_id"`
FullID string `json:"name"`
Permalink string `json:"permalink"`
Score float64 `json:"score"`
UpVotes float64 `json:"ups"`
DownVotes float64 `json:"downs"`
Created float64 `json:"created_utc"`
Archived bool `json:"archived"`
Edited bool `json:"edited"`
Likes bool `json:"likes"`
BannedBy *string `json:"banned_by"`
ApprovedBy *string `json:"approved_by"`
AuthorFlairTxt *string `json:"author_flair_text"`
AuthorFlairCSSClass *string `json:"author_flair_css_class"`
NumReports *int `json:"num_reports"`
Replies []*Comment
}

Expand Down Expand Up @@ -62,13 +63,14 @@ func makeComment(cmap map[string]interface{}) *Comment {
ret.UpVotes, _ = cmap["ups"].(float64)
ret.DownVotes, _ = cmap["downs"].(float64)
ret.Created, _ = cmap["created_utc"].(float64)
ret.Archived, _ = cmap["archived"].(bool)
ret.Edited, _ = cmap["edited"].(bool)
ret.Likes, _ = cmap["likes"].(bool)
ret.BannedBy, _ = cmap["banned_by"].(*string)
ret.ApprovedBy, _ = cmap["approved_by"].(*string)
ret.AuthorFlairTxt, _ = cmap["author_flair_text"].(*string)
ret.AuthorFlairCSSClass, _ = cmap["author_flair_css_class"].(*string)
ret.NumReports, _ = cmap["num_reports"].(*int)
ret.Likes, _ = cmap["likes"].(*int)

helper := new(helper)
helper.buildComments(cmap["replies"])
Expand All @@ -85,7 +87,18 @@ type helper struct {
//Recursive function to find the fields we want and build the Comments
//Way too hackish for my likes
func (h *helper) buildComments(inf interface{}) {
type listing struct {
Data struct {
Children []struct {
Data interface{}
}
}
}
switch tp := inf.(type) {
case listing: //Maybe a listing of comments
for _, c := range tp.Data.Children {
h.buildComments(c)
}
case []interface{}: //Maybe array for base comments
for _, k := range tp {
h.buildComments(k)
Expand Down
6 changes: 3 additions & 3 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import (
"fmt"
"log"

"github.com/jzelinskie/geddit"
"github.com/khipkin/geddit"
)

func ExampleNewOAuthSession_login() {
o, err := geddit.NewOAuthSession(
"client_id",
"client_secret",
"Testing OAuth Bot by u/my_user v0.1 see source https://github.com/jzelinskie/geddit",
"Testing OAuth Bot by u/my_user v0.1 see source https://github.com/khipkin/geddit",
"http://redirect.url",
)
if err != nil {
Expand All @@ -35,7 +35,7 @@ func ExampleNewOAuthSession_url() {
o, err := geddit.NewOAuthSession(
"client_id",
"client_secret",
"Testing OAuth Bot by u/my_user v0.1 see source https://github.com/jzelinskie/geddit",
"Testing OAuth Bot by u/my_user v0.1 see source https://github.com/khipkin/geddit",
"http://redirect.url",
)
if err != nil {
Expand Down
110 changes: 109 additions & 1 deletion oauth_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewOAuthSession(clientID, clientSecret, useragent, redirectURL string) (*OA
if len(useragent) > 0 {
o.UserAgent = useragent
} else {
o.UserAgent = "Geddit Reddit Bot https://github.com/jzelinskie/geddit"
o.UserAgent = "Geddit Reddit Bot https://github.com/khipkin/geddit"
}

// Set OAuth config
Expand Down Expand Up @@ -373,6 +373,114 @@ func (o *OAuthSession) Comments(h *Submission, sort PopularitySort, params Listi
return helper.comments, nil
}

// Link returns the link with the given globally-unique full ID.
func (o *OAuthSession) Link(fullID string) (*Submission, error) {
type resp struct {
Data struct {
Children []struct {
Data *Submission
}
}
}
r := &resp{}
url := fmt.Sprintf("https://oauth.reddit.com/by_id/%s", fullID)

if err := o.getBody(url, r); err != nil {
return nil, err
}
if len(r.Data.Children) == 0 {
return nil, errors.New("No link with the given ID was found")
}
if len(r.Data.Children) > 1 {
return nil, errors.New("Got unexpected number of resources with the given ID")
}
return r.Data.Children[0].Data, nil
}

// Comment returns the comment with the given globally-unique full ID.
func (o *OAuthSession) Comment(subreddit, fullID string) (*Comment, error) {
baseURL := "https://oauth.reddit.com"
// If subbreddit given, add to URL
if subreddit != "" {
baseURL += "/r/" + subreddit
}
url := fmt.Sprintf("%s/api/info/?id=%s", baseURL, fullID)

var c interface{}
if err := o.getBody(url, &c); err != nil {
return nil, err
}
helper := new(helper)
helper.buildComments(c)

if len(helper.comments) == 0 {
return nil, errors.New("No comment with the given ID was found")
}
if len(helper.comments) > 1 {
return nil, errors.New("Got unexpected number of resources with the given ID")
}
return helper.comments[0], nil
}

// UserPosts returns the posts for the given user in the given subreddit (if provided).
func (o *OAuthSession) UserPosts(subreddit, username string, sort PopularitySort, params ListingOptions) ([]*Submission, error) {
type Response struct {
Data struct {
Children []struct {
Data *Submission
}
}
}

v, err := query.Values(params)
if err != nil {
return nil, err
}
baseURL := "https://oauth.reddit.com"
redditURL := fmt.Sprintf("%s/user/%s/submitted?sr_detail=1&sort=%s&type=links&%s", baseURL, username, sort, v.Encode())

r := new(Response)
err = o.getBody(redditURL, r)
if err != nil {
return nil, err
}

submissions := []*Submission{}
for _, child := range r.Data.Children {
if subreddit != "" && strings.ToLower(child.Data.Subreddit) == strings.ToLower(subreddit) {
submissions = append(submissions, child.Data)
}
}
return submissions, nil
}

// UserComments returns the comments for the given user in the given subreddit (if provided).
func (o *OAuthSession) UserComments(subreddit, username string, sort PopularitySort, params ListingOptions) ([]*Comment, error) {
v, err := query.Values(params)
if err != nil {
return nil, err
}
baseURL := "https://oauth.reddit.com"
redditURL := fmt.Sprintf("%s/user/%s/comments?sr_detail=1&sort=%s&type=links&%s", baseURL, username, sort, v.Encode())

var s interface{}
err = o.getBody(redditURL, &s)
if err != nil {
return nil, err
}

helper := new(helper)
helper.buildComments(s)

comments := []*Comment{}
for _, c := range helper.comments {
if subreddit != "" && strings.ToLower(c.Subreddit) == strings.ToLower(subreddit) {
comments = append(comments, c)
}
}
return comments, nil
}

func (o *OAuthSession) postBody(link string, form url.Values, d interface{}) error {
req, err := http.NewRequest("POST", link, strings.NewReader(form.Encode()))
if err != nil {
Expand Down
96 changes: 96 additions & 0 deletions oauth_session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,101 @@ func TestMe(t *testing.T) {
t.Fatalf("Me.String() returns unexpected result: %s", me.String())
}
fmt.Println(me)
}

func TestLink(t *testing.T) {
server, oauth := testTools(200, `{"data": {"children": [{"data": {"name": "t3_12345", "id": "12345", "title": "My Title"}}]}}`)
defer server.Close()

link, err := oauth.Link("t3_12345")
if err != nil {
t.Errorf("Link() Test failed: %v", err)
}

if link.FullID != "t3_12345" {
t.Fatalf("Link() returned unexpected full ID: %s", link.FullID)
}
if link.ID != "12345" {
t.Fatalf("Link() returned unexpected ID: %s", link.ID)
}
if link.Title != "My Title" {
t.Fatalf("Link() returned unexpected title: %s", link.Title)
}
}

func TestComment(t *testing.T) {
server, oauth := testTools(200, `{"data": {"children": [{"data": {"name": "t1_12345", "author": "u/me", "body": "username checks out", "archived": false}}]}}`)
defer server.Close()

comment, err := oauth.Comment("", "t1_12345")
if err != nil {
t.Errorf("Comment() Test failed: %v", err)
}

if comment.FullID != "t1_12345" {
t.Fatalf("Comment() returned unexpected full ID: %s", comment.FullID)
}
if comment.Author != "u/me" {
t.Fatalf("Comment() returned unexpected ID: %s", comment.Author)
}
if comment.Body != "username checks out" {
t.Fatalf("Comment() returned unexpected body: %s", comment.Body)
}
if comment.Archived != false {
t.Fatalf("Comment() returned wrong archived value: %v", comment.Archived)
}
}

func TestUserPosts(t *testing.T) {
server, oauth := testTools(200, `{"data": {"children": [{"data": {"name": "t3_12345", "title": "My Title", "permalink": "www.example.com", "subreddit": "example"}}, {"data": {"name": "t3_56789", "title": "My Title", "permalink": "www.notexample.com", "subreddit": "notexample"}}]}}`)
defer server.Close()

posts, err := oauth.UserPosts("example", "u/me", NewSubmissions, ListingOptions{})
if err != nil {
t.Errorf("UserPosts() Test failed: %v", err)
}

if len(posts) != 1 {
t.Fatalf("UserPosts() failed to filter by subreddit (got %d results, want %d results", len(posts), 1)
}
p := posts[0]
if p.FullID != "t3_12345" {
t.Fatalf("UserPosts() returned unexpected full ID: %s", p.FullID)
}
if p.Title != "My Title" {
t.Fatalf("UserPosts() returned unexpected title: %s", p.Author)
}
if p.Permalink != "www.example.com" {
t.Fatalf("UserPosts() returned unexpected permalink: %s", p.Permalink)
}
if p.Subreddit != "example" {
t.Fatalf("UserPosts() returned wrong subreddit: %v", p.Subreddit)
}
}

func TestUserComments(t *testing.T) {
server, oauth := testTools(200, `{"data": {"children": [{"data": {"name": "t1_12345", "body": "My Body", "permalink": "www.example.com", "subreddit": "example"}}, {"data": {"name": "t1_56789", "body": "My Body", "permalink": "www.notexample.com", "subreddit": "notexample"}}]}}`)
defer server.Close()

comments, err := oauth.UserComments("example", "u/me", NewSubmissions, ListingOptions{})
if err != nil {
t.Errorf("UserComments() Test failed: %v", err)
}

if len(comments) != 1 {
t.Fatalf("UserComments() failed to filter by subreddit (got %d results, want %d results", len(comments), 1)
}
c := comments[0]
if c.FullID != "t1_12345" {
t.Fatalf("UserComments() returned unexpected full ID: %s", c.FullID)
}
if c.Body != "My Body" {
t.Fatalf("UserComments() returned unexpected body: %s", c.Author)
}
if c.Permalink != "www.example.com" {
t.Fatalf("UserComments() returned unexpected permalink: %s", c.Permalink)
}
if c.Subreddit != "example" {
t.Fatalf("UserComments() returned wrong subreddit: %v", c.Subreddit)
}
}