bterlson-reddit 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/reddit/article.rb +4 -2
- data/lib/reddit/comment.rb +4 -2
- data/lib/reddit/comment_list.rb +4 -9
- data/lib/reddit/reddit.rb +21 -17
- data/lib/reddit/resource_list.rb +25 -11
- data/lib/reddit/session.rb +1 -1
- data/lib/reddit/user.rb +5 -8
- data/lib/reddit/version.rb +2 -2
- data/spec/article_spec.rb +1 -1
- data/spec/comment_list_spec.rb +2 -6
- data/spec/reddit_spec.rb +13 -8
- data/spec/resource_list_spec.rb +13 -2
- data/spec/user_spec.rb +1 -7
- metadata +3 -3
- data/README.txt +0 -66
data/lib/reddit/article.rb
CHANGED
@@ -15,6 +15,7 @@ module Reddit
|
|
15
15
|
@domain = attributes['domain']
|
16
16
|
@author = User.new(attributes['author']) unless attributes['author'].nil?
|
17
17
|
@id = attributes['id']
|
18
|
+
# Reddit's created_at timestamps are currently wonky, so this will return the wrong time.
|
18
19
|
@created_at = Time.at(attributes['created']) unless attributes['created'].nil?
|
19
20
|
@saved = attributes['saved']
|
20
21
|
@clicked = attributes['clicked']
|
@@ -37,8 +38,9 @@ module Reddit
|
|
37
38
|
end
|
38
39
|
|
39
40
|
# returns a CommentList of this article's comments.
|
40
|
-
def comments
|
41
|
-
|
41
|
+
def comments(options = {})
|
42
|
+
@comments_list ||= CommentList.new(@id)
|
43
|
+
return @comments_list.top_level(options)
|
42
44
|
end
|
43
45
|
end
|
44
46
|
end
|
data/lib/reddit/comment.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Reddit
|
2
|
-
|
3
2
|
# A reddit comment.
|
4
3
|
class Comment
|
5
4
|
attr_reader :body, :name, :ups, :downs, :url, :domain, :author, :id, :created_at, :replies
|
@@ -21,7 +20,6 @@ module Reddit
|
|
21
20
|
@replies << Comment.new(reply['data'])
|
22
21
|
end
|
23
22
|
end
|
24
|
-
|
25
23
|
end
|
26
24
|
|
27
25
|
# Returns the score for this comment.
|
@@ -29,5 +27,9 @@ module Reddit
|
|
29
27
|
return @ups - @downs
|
30
28
|
end
|
31
29
|
|
30
|
+
# returns a number representing how controversial this comment is
|
31
|
+
def controversy_score
|
32
|
+
(@ups + @downs).to_f / [score.abs, 1].max
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
data/lib/reddit/comment_list.rb
CHANGED
@@ -10,15 +10,10 @@ module Reddit
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# returns the top level comments for the thread.
|
13
|
-
def top_level
|
14
|
-
|
15
|
-
|
16
|
-
comments = []
|
17
|
-
resources.each do |comment|
|
18
|
-
comments << Comment.new(comment['data'])
|
13
|
+
def top_level(options = {})
|
14
|
+
get_resources(@url, :querystring => options[:querystring], :count => options[:count]) do |resource_json|
|
15
|
+
comment = Comment.new(resource_json['data'])
|
19
16
|
end
|
20
|
-
|
21
|
-
return comments
|
22
17
|
end
|
23
18
|
|
24
19
|
private
|
@@ -26,6 +21,6 @@ module Reddit
|
|
26
21
|
# forward any method calls to the top level comments array.
|
27
22
|
def method_missing(meth, *args, &block)
|
28
23
|
top_level.send(meth, *args, &block)
|
29
|
-
end
|
24
|
+
end
|
30
25
|
end
|
31
26
|
end
|
data/lib/reddit/reddit.rb
CHANGED
@@ -9,33 +9,37 @@ module Reddit
|
|
9
9
|
@url = @name.nil? ? BASE_URL : SUBREDDIT_URL.gsub('[subreddit]', @name)
|
10
10
|
end
|
11
11
|
|
12
|
-
def hot
|
13
|
-
articles 'hot'
|
12
|
+
def hot(options = {})
|
13
|
+
articles 'hot', options
|
14
14
|
end
|
15
15
|
|
16
|
-
def top
|
17
|
-
articles 'top'
|
16
|
+
def top(options = {})
|
17
|
+
articles 'top', options
|
18
18
|
end
|
19
19
|
|
20
|
-
def new
|
21
|
-
|
20
|
+
def new(options = {})
|
21
|
+
options[:querystring] = 'sort=new'
|
22
|
+
articles 'new', options
|
22
23
|
end
|
23
24
|
|
24
|
-
def
|
25
|
-
|
25
|
+
def rising(options = {})
|
26
|
+
options[:querystring] = 'sort=rising'
|
27
|
+
articles 'new', options
|
28
|
+
end
|
29
|
+
|
30
|
+
def controversial(options = {})
|
31
|
+
articles 'controversial', options
|
26
32
|
end
|
27
33
|
|
28
34
|
# Returns the articles found in this reddit.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
# Options are:
|
36
|
+
# Count: Return at least this many articles.
|
37
|
+
# Querystring: Querystring to append to resource request
|
38
|
+
|
39
|
+
def articles(page = 'hot', options = {})
|
40
|
+
get_resources("#{@url}#{page}", options) do |resource_json|
|
41
|
+
Article.new(resource_json['data'])
|
36
42
|
end
|
37
|
-
|
38
|
-
return articles
|
39
43
|
end
|
40
44
|
end
|
41
45
|
end
|
data/lib/reddit/resource_list.rb
CHANGED
@@ -7,22 +7,36 @@ module Reddit
|
|
7
7
|
private
|
8
8
|
|
9
9
|
# Grabs the resources at the URL and returns the parsed json.
|
10
|
-
def get_resources(url)
|
11
|
-
|
10
|
+
def get_resources(url, options = {}, &block)
|
11
|
+
querystring = options.delete(:querystring) || ''
|
12
|
+
count = options.delete(:count) || 25
|
12
13
|
url = URI.parse(url)
|
14
|
+
items = []
|
15
|
+
after = ''
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
while items.size < count
|
18
|
+
res = Net::HTTP.start(url.host, url.port) {|http|
|
19
|
+
http.get("#{url.path}.json?#{querystring}&after=#{after}&limit=#{count - items.size}")
|
20
|
+
}
|
17
21
|
|
18
|
-
|
19
|
-
resources = JSON.parse(res.body, :max_nesting => 0)
|
22
|
+
raise SubredditNotFound if res.is_a?(Net::HTTPRedirection)
|
20
23
|
|
21
|
-
|
22
|
-
# and the second is the actual comments. This is hackish.
|
23
|
-
resources = resources.last if resources.is_a?(Array)
|
24
|
+
resources = JSON.parse(res.body, :max_nesting => 0)
|
24
25
|
|
25
|
-
|
26
|
+
# comments pages are contained in an array where the first element is the article
|
27
|
+
# and the second is the actual comments. This is hackish.
|
28
|
+
resources = resources.last if resources.is_a?(Array)
|
29
|
+
resources = resources['data']['children']
|
30
|
+
break if resources.size == 0
|
31
|
+
resources.each do |resource|
|
32
|
+
items << yield(resource)
|
33
|
+
end
|
34
|
+
|
35
|
+
after = items.last.name
|
36
|
+
end
|
37
|
+
|
38
|
+
items
|
26
39
|
end
|
27
40
|
end
|
41
|
+
|
28
42
|
end
|
data/lib/reddit/session.rb
CHANGED
@@ -2,7 +2,7 @@ module Reddit
|
|
2
2
|
BASE_URL = "http://www.reddit.com/"
|
3
3
|
PROFILE_URL = BASE_URL + "user/[username]/"
|
4
4
|
SUBREDDIT_URL = BASE_URL + "r/[subreddit]/"
|
5
|
-
COMMENTS_URL = BASE_URL + "
|
5
|
+
COMMENTS_URL = BASE_URL + "comments/[id]/"
|
6
6
|
|
7
7
|
# raised when attempting to interact with a subreddit that doesn't exist.
|
8
8
|
class SubredditNotFound < StandardError; end
|
data/lib/reddit/user.rb
CHANGED
@@ -11,15 +11,12 @@ module Reddit
|
|
11
11
|
end
|
12
12
|
|
13
13
|
# Get the user's comments.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
comments
|
18
|
-
|
19
|
-
comments << Comment.new(comment['data'])
|
14
|
+
# Options can include a limit, which sets the number of comments to return.
|
15
|
+
|
16
|
+
def comments(options = {})
|
17
|
+
get_resources("#{@url}comments/", :querystring => options[:querystring], :count => options[:count]) do |resource_json|
|
18
|
+
Comment.new(resource_json['data'])
|
20
19
|
end
|
21
|
-
|
22
|
-
return comments
|
23
20
|
end
|
24
21
|
end
|
25
22
|
end
|
data/lib/reddit/version.rb
CHANGED
data/spec/article_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Reddit::Article do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
it "should be able to get the article's comments comments" do
|
9
|
-
Reddit::CommentList.should_receive(:new).with("id").and_return("reddit!")
|
9
|
+
Reddit::CommentList.should_receive(:new).with("id").and_return(mock(Reddit::CommentList, :top_level => "reddit!"))
|
10
10
|
@article.comments.should == "reddit!"
|
11
11
|
end
|
12
12
|
end
|
data/spec/comment_list_spec.rb
CHANGED
@@ -10,13 +10,9 @@ describe Reddit::CommentList do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should fetch the top level comments" do
|
13
|
-
@comments_list.should_receive(:get_resources).and_return([
|
14
|
-
{:type => 't1', :data => {:attribute => 'value'}},
|
15
|
-
{:type => 't1', :data => {:attribute => 'value2'}}
|
16
|
-
])
|
17
|
-
|
18
13
|
mock_comment = mock(Reddit::Comment)
|
19
|
-
|
14
|
+
|
15
|
+
@comments_list.should_receive(:get_resources).and_return([mock_comment, mock_comment])
|
20
16
|
|
21
17
|
@comments_list.top_level.should == [mock_comment, mock_comment]
|
22
18
|
end
|
data/spec/reddit_spec.rb
CHANGED
@@ -17,18 +17,15 @@ describe Reddit::Reddit do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should find the articles" do
|
20
|
-
@reddit.should_receive(:get_resources).and_return(test_articles)
|
21
|
-
|
22
20
|
mock_article = mock(Reddit::Article)
|
23
|
-
|
24
|
-
|
21
|
+
@reddit.should_receive(:get_resources).and_return([mock_article, mock_article])
|
25
22
|
@reddit.articles.should == [mock_article, mock_article]
|
26
23
|
end
|
27
24
|
|
28
25
|
it "should find top articles" do
|
29
26
|
mock_article = mock(Reddit::Article)
|
30
27
|
|
31
|
-
@reddit.should_receive(:articles).with('top').and_return([mock_article, mock_article])
|
28
|
+
@reddit.should_receive(:articles).with('top', {}).and_return([mock_article, mock_article])
|
32
29
|
|
33
30
|
@reddit.top.should == [mock_article, mock_article]
|
34
31
|
end
|
@@ -36,15 +33,23 @@ describe Reddit::Reddit do
|
|
36
33
|
it "should find new articles" do
|
37
34
|
mock_article = mock(Reddit::Article)
|
38
35
|
|
39
|
-
@reddit.should_receive(:articles).with('new').and_return([mock_article, mock_article])
|
36
|
+
@reddit.should_receive(:articles).with('new', {:querystring => 'sort=new'}).and_return([mock_article, mock_article])
|
40
37
|
|
41
38
|
@reddit.new.should == [mock_article, mock_article]
|
42
39
|
end
|
43
40
|
|
41
|
+
it "should find rising articles" do
|
42
|
+
mock_article = mock(Reddit::Article)
|
43
|
+
|
44
|
+
@reddit.should_receive(:articles).with('new', {:querystring => 'sort=rising'}).and_return([mock_article, mock_article])
|
45
|
+
|
46
|
+
@reddit.rising.should == [mock_article, mock_article]
|
47
|
+
end
|
48
|
+
|
44
49
|
it "should find controversial articles" do
|
45
50
|
mock_article = mock(Reddit::Article)
|
46
51
|
|
47
|
-
@reddit.should_receive(:articles).with('controversial').and_return([mock_article, mock_article])
|
52
|
+
@reddit.should_receive(:articles).with('controversial', {}).and_return([mock_article, mock_article])
|
48
53
|
|
49
54
|
@reddit.controversial.should == [mock_article, mock_article]
|
50
55
|
end
|
@@ -52,7 +57,7 @@ describe Reddit::Reddit do
|
|
52
57
|
it "should find hot articles" do
|
53
58
|
mock_article = mock(Reddit::Article)
|
54
59
|
|
55
|
-
@reddit.should_receive(:articles).with('hot').and_return([mock_article, mock_article])
|
60
|
+
@reddit.should_receive(:articles).with('hot', {}).and_return([mock_article, mock_article])
|
56
61
|
|
57
62
|
@reddit.hot.should == [mock_article, mock_article]
|
58
63
|
end
|
data/spec/resource_list_spec.rb
CHANGED
@@ -12,12 +12,23 @@ describe Reddit::ResourceList, ".get_resources" do
|
|
12
12
|
|
13
13
|
it "should get the resources from Reddit" do
|
14
14
|
Net::HTTP.should_receive(:start).and_yield(@http_mock).and_return(@response_mock)
|
15
|
-
@resource_list.send(:get_resources, "http://reddit.com")
|
15
|
+
@resource_list.send(:get_resources, "http://reddit.com", :count => 1) do
|
16
|
+
mock('object', :name => "object_name")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should get the specified number of resources" do
|
21
|
+
Net::HTTP.should_receive(:start).exactly(:twice).and_yield(@http_mock).and_return(@response_mock)
|
22
|
+
@resource_list.send(:get_resources, "http://reddit.com", :count => 2) do
|
23
|
+
mock('object', :name => "object_name")
|
24
|
+
end
|
16
25
|
end
|
17
26
|
|
18
27
|
it "should parse the JSON" do
|
19
28
|
JSON.should_receive(:parse).and_return({'kind' => 'Listing', 'data' => {'children' => [{'data' => {'attribute' => 'value'}}]}})
|
20
|
-
@resource_list.send(:get_resources, "http://reddit.com")
|
29
|
+
@resource_list.send(:get_resources, "http://reddit.com", :count => 1) do
|
30
|
+
mock('object', :name => "object_name")
|
31
|
+
end
|
21
32
|
end
|
22
33
|
|
23
34
|
it "should raise an error when the subreddit is not found" do
|
data/spec/user_spec.rb
CHANGED
@@ -10,14 +10,8 @@ describe Reddit::User do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should fetch the user's comments" do
|
13
|
-
@user.should_receive(:get_resources).and_return([
|
14
|
-
{:type => 't1', :data => {:attribute => 'value'}},
|
15
|
-
{:type => 't1', :data => {:attribute => 'value2'}}
|
16
|
-
])
|
17
|
-
|
18
13
|
mock_comment = mock(Reddit::Comment)
|
19
|
-
|
20
|
-
|
14
|
+
@user.should_receive(:get_resources).and_return([mock_comment, mock_comment])
|
21
15
|
@user.comments.should == [mock_comment, mock_comment]
|
22
16
|
end
|
23
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bterlson-reddit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Terlson
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-08-13 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
77
|
requirements: []
|
78
78
|
|
79
79
|
rubyforge_project:
|
80
|
-
rubygems_version: 1.0
|
80
|
+
rubygems_version: 1.2.0
|
81
81
|
signing_key:
|
82
82
|
specification_version: 2
|
83
83
|
summary: Interface with the Reddit.com API.
|
data/README.txt
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
= reddit
|
2
|
-
|
3
|
-
* http://github.com/bterlson/reddit/
|
4
|
-
|
5
|
-
== DESCRIPTION:
|
6
|
-
|
7
|
-
An interface to the reddit API.
|
8
|
-
|
9
|
-
== FEATURES/PROBLEMS:
|
10
|
-
|
11
|
-
* Retreive articles and their comments
|
12
|
-
* Retreive user pages
|
13
|
-
|
14
|
-
== SYNOPSIS:
|
15
|
-
|
16
|
-
require 'rubygems'
|
17
|
-
require 'reddit'
|
18
|
-
|
19
|
-
reddit = Reddit::Session.new
|
20
|
-
|
21
|
-
reddit.main.articles.each do |article|
|
22
|
-
p article.url
|
23
|
-
|
24
|
-
article.comments.each do |comment|
|
25
|
-
p comment.body
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
p reddit.subreddit("programming").articles[1].author
|
30
|
-
|
31
|
-
reddit.user("radhruin").comments.each do |comment|
|
32
|
-
p comment.body
|
33
|
-
end
|
34
|
-
|
35
|
-
== REQUIREMENTS:
|
36
|
-
|
37
|
-
* JSON >= 1.1.2
|
38
|
-
|
39
|
-
== INSTALL:
|
40
|
-
|
41
|
-
* sudo gem install bterlson-reddit --source=http://gems.github.com
|
42
|
-
|
43
|
-
== LICENSE:
|
44
|
-
|
45
|
-
(The MIT License)
|
46
|
-
|
47
|
-
Copyright (c) 2008 FIX
|
48
|
-
|
49
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
50
|
-
a copy of this software and associated documentation files (the
|
51
|
-
'Software'), to deal in the Software without restriction, including
|
52
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
53
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
54
|
-
permit persons to whom the Software is furnished to do so, subject to
|
55
|
-
the following conditions:
|
56
|
-
|
57
|
-
The above copyright notice and this permission notice shall be
|
58
|
-
included in all copies or substantial portions of the Software.
|
59
|
-
|
60
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
61
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
62
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
63
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
64
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
65
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
66
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|