ruby_reddit_api 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,47 @@
1
+ Ruby Reddit Client v0.1.9
2
+ ==================
3
+ Tested with 1.9.2
4
+
5
+ Usage:
6
+ =======
7
+ > require "ruby_reddit_api"
8
+ > r = Reddit::Api.new "user", "password"
9
+ > results = r.browse "ruby"
10
+ > results[0].upvote
11
+
12
+ Features:
13
+ ========
14
+ - Authentication
15
+ - Parse submissions
16
+ - Comments parsing
17
+ - Vote on submission
18
+
19
+
20
+ Running Tests:
21
+ =============
22
+ - Set up the reddit VM (http://blog.reddit.com/2010/05/admins-never-do-what-you-want-now-it-is.html)
23
+ - Ensure your hosts file has reddit.local pointing to the VM
24
+ - rake cucumber
25
+
26
+ License
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2010 James Cook
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ of this software and associated documentation files (the "Software"), to deal
33
+ in the Software without restriction, including without limitation the rights
34
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ copies of the Software, and to permit persons to whom the Software is
36
+ furnished to do so, subject to the following conditions:
37
+
38
+ The above copyright notice and this permission notice shall be included in
39
+ all copies or substantial portions of the Software.
40
+
41
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ THE SOFTWARE.
@@ -0,0 +1,10 @@
1
+ Feature: Browsing
2
+ I want to be able to browse submissions
3
+
4
+ Scenario: Valid subreddit
5
+ Given I submit a valid subreddit
6
+ Then I should get back a listing of submissions
7
+
8
+ Scenario: Invalid subreddit
9
+ Given I submit a invalid subreddit
10
+ Then I should get back some error
@@ -0,0 +1,15 @@
1
+ Feature: Authentication
2
+ In order perform things like voting and commenting
3
+ As a Redditor
4
+ I want to be able to login in my step definitions
5
+
6
+ Scenario: Valid user and password
7
+ Given I have a valid user
8
+ And I send my user and password to the login API
9
+ Then I should have a valid cookie
10
+ And the stored headers should refer to the cookie
11
+
12
+ Scenario: Invalid user and password
13
+ Given I have a invalid user
14
+ And I send my user and password to the login API
15
+ Then I should not have a valid cookie
@@ -0,0 +1,40 @@
1
+ Feature: Comments
2
+ I want to be able to comment on a comment
3
+ I want to be able to delete my comments
4
+
5
+ Scenario: Valid comment text
6
+ Given I enter some text
7
+ Then I should be able to add a comment
8
+
9
+ Scenario: I want to hide a comment
10
+ Given I have a comment
11
+ Then I should be able to hide the comment
12
+
13
+ Scenario: I want to remove a comment
14
+ Given I have a comment
15
+ Then I should be able to remove the comment
16
+
17
+ Scenario: I want to approve a comment
18
+ Given I have a comment
19
+ Then I should be able to approve the comment
20
+
21
+ Scenario: I want to edit a comment
22
+ Given I have a comment
23
+ Then I should be able to edit the comment
24
+
25
+ Scenario: I want to comment on a comment
26
+ Given I have a comment
27
+ Then I should be able to reply to the comment
28
+
29
+ Scenario: I want to moderator distinguish a comment
30
+ Given I have a comment
31
+ Then I should be able to moderator distinguish the comment
32
+
33
+ Scenario: I want to indistinguish a comment
34
+ Given I have a comment
35
+ Then I should be able to indistinguish the comment
36
+
37
+ Scenario: I want to admin distinguish a comment
38
+ Given I have a comment
39
+ Then I should be able to admin distinguish the comment
40
+
@@ -0,0 +1,5 @@
1
+ Feature: Messaging
2
+ Scenario: I want to be able to read my sent messages
3
+ Given I am logged in
4
+ When I go to the sent messages page
5
+ Then I should see a listing of messages
@@ -0,0 +1,5 @@
1
+ server:
2
+ address: "reddit.local"
3
+ port: 80
4
+ test_user: "reddit"
5
+ test_pass: "password"
@@ -0,0 +1,22 @@
1
+ Given /^I submit a valid subreddit$/ do
2
+ Reddit::Api.base_uri "reddit.local"
3
+ @api = Reddit::Api.new "reddit", "password"
4
+ @subreddit = "reddit_test0"
5
+ end
6
+
7
+ Then /^I should get back a listing of submissions$/ do
8
+ results = @api.browse(@subreddit)
9
+ results[0].class.should == Reddit::Submission
10
+ results[0].author.should_not == nil
11
+ end
12
+
13
+ Given /^I submit a invalid subreddit$/ do
14
+ Reddit::Api.base_uri "reddit.local"
15
+ @api = Reddit::Api.new "reddit", "password"
16
+ @subreddit = "invalid_subreddit"
17
+ end
18
+
19
+ Then /^I should get back some error$/ do
20
+ results = @api.browse(@subreddit)
21
+ results.should == false
22
+ end
@@ -0,0 +1,49 @@
1
+ require File.join( File.dirname(__FILE__), "..", "..", "lib", "ruby_reddit_api.rb")
2
+ Before do
3
+ Reddit::Base.instance_variable_set("@cookie", nil)
4
+ load_server_config
5
+ Reddit::Api.base_uri @address
6
+ end
7
+
8
+ Given /^I have a valid user$/ do
9
+ load_server_config
10
+ end
11
+
12
+ Given /^I have a invalid user$/ do
13
+ @user, @pass = "invalid", "user"
14
+ end
15
+
16
+ Given /^I send my user and password to the login API$/ do
17
+ @api = Reddit::Api.new @user, @pass
18
+ @api.login
19
+ end
20
+
21
+ Given /I'm logged in$/ do
22
+ @api = Reddit::Api.new @user, @pass
23
+ @api.login
24
+ end
25
+
26
+ Given /I'm not logged in$/ do
27
+ @api.logout if @api
28
+ @api = Reddit::Api.new @user, "bad pass"
29
+ @api.logout
30
+ end
31
+
32
+ Then /^I should have a valid cookie$/ do
33
+ @api.cookie.should_not == nil
34
+ @api.cookie.should =~ /reddit_session/
35
+ end
36
+
37
+ Then /^I should not have a valid cookie$/ do
38
+ @api.cookie.should_not == nil
39
+ @api.cookie.should =~ /reddit_first/
40
+ end
41
+
42
+ Then /^I should not have a cookie$/ do
43
+ @api.cookie.should == nil
44
+ end
45
+
46
+ Then /^the stored headers should refer to the cookie$/ do
47
+ @api.base_headers["Cookie"].should == @api.cookie
48
+ end
49
+
@@ -0,0 +1,59 @@
1
+ Before do
2
+ load_server_config
3
+ Reddit::Api.base_uri @address
4
+ Reddit::Submission.base_uri @address
5
+ Reddit::Comment.base_uri @address
6
+ @api = Reddit::Api.new @user, @pass
7
+ @api.login
8
+ @submission ||= @api.browse("reddit_test0")[0]
9
+ end
10
+
11
+ Given /^I enter some text$/ do
12
+ @text = "SOME COMMENT"
13
+ end
14
+
15
+ Then /^I should be able to add a comment$/ do
16
+ @submission.add_comment(@text).should be true
17
+ end
18
+
19
+ Given /^I have a comment$/ do
20
+ @submission.add_comment("a comment")
21
+ @comment = @submission.comments.last
22
+ end
23
+
24
+ Then /^I should be able to hide the comment$/ do
25
+ @comment.hide
26
+ end
27
+
28
+ Then /^I should be able to remove the comment$/ do
29
+ @comment.remove
30
+ end
31
+
32
+ Then /^I should be able to approve the comment$/ do
33
+ @comment.approve
34
+ end
35
+
36
+ Then /^I should not be able to edit the comment$/ do
37
+ @comment.edit( "1234" ).should be false
38
+ end
39
+
40
+ Then /^I should be able to edit the comment$/ do
41
+ @comment.edit( "1234" ).should be true
42
+ end
43
+
44
+ Then /^I should be able to moderator distinguish the comment$/ do
45
+ pending #@comment.moderator_distinguish
46
+ end
47
+
48
+ Then /^I should be able to indistinguish the comment$/ do
49
+ pending #@comment.indistinguish
50
+ end
51
+
52
+ Then /^I should be able to admin distinguish the comment$/ do
53
+ pending #@comment.admin_distinguish
54
+ end
55
+
56
+ Then /^I should be able to reply to the comment$/ do
57
+ pending #@comment.reply("a reply").should be true
58
+ end
59
+
@@ -0,0 +1,18 @@
1
+ Before do
2
+ load_server_config
3
+ Reddit::Api.base_uri @address
4
+ Reddit::Message.base_uri @address
5
+ end
6
+
7
+ Given /^I am logged in$/ do
8
+ @api = Reddit::Api.new @user, @pass
9
+ @api.login
10
+ end
11
+
12
+ When /^I go to the sent messages page$/ do
13
+ @result = @api.sent_messages
14
+ end
15
+
16
+ Then /^I should see a listing of messages$/ do
17
+ @result.any?{|r| r.is_a?(Reddit::Message) == false}.should be false
18
+ end
@@ -0,0 +1,117 @@
1
+ Given /^I have a submission$/ do
2
+ load_server_config
3
+ Reddit::Api.base_uri @address
4
+ Reddit::Submission.base_uri @address
5
+ Reddit::Comment.base_uri @address
6
+ @api = Reddit::Api.new @user, @pass
7
+ @api.login
8
+ @submission = @api.browse("reddit_test0")[0]
9
+ if @api.logged_in?
10
+ @submission.add_comment("STOP REPOSTING!!1") if @submission
11
+ else
12
+ raise "Can't run test. Submit failed.."
13
+ end
14
+ end
15
+
16
+ Then /^I should be able to see the author$/ do
17
+ @submission.author.should_not == nil
18
+ end
19
+
20
+ Then /^I should be able to see the title$/ do
21
+ @submission.title.should_not == nil
22
+ end
23
+
24
+ Then /^I should be able to see the selftext$/ do
25
+ @submission.selftext.should_not == nil
26
+ end
27
+
28
+ Then /^I should be able to see the url$/ do
29
+ @submission.url.should_not == nil
30
+ end
31
+
32
+ Then /^I should be able to see the up votes$/ do
33
+ @submission.ups.should_not == nil
34
+ end
35
+
36
+ Then /^I should be able to see the down votes$/ do
37
+ @submission.downs.should_not == nil
38
+ end
39
+
40
+ Then /^I should not be able to upvote it$/ do
41
+ @submission.upvote.should be false
42
+ end
43
+
44
+ Then /^I should not be able to downvote it$/ do
45
+ @submission.downvote.should be false
46
+ end
47
+
48
+ Then /^I should be able to upvote it$/ do
49
+ @submission.upvote.should be true
50
+ end
51
+
52
+ Then /^I should be able to downvote it$/ do
53
+ @submission.downvote.should be true
54
+ end
55
+
56
+ Then /^I should be able to see the comments$/ do
57
+ comments = @submission.comments
58
+ comments.size.should > 0
59
+ end
60
+
61
+ Then /^I should not be able to save the submission$/ do
62
+ @submission.save.should be false
63
+ end
64
+
65
+ Then /^I should not be able to unsave the submission$/ do
66
+ @submission.unsave.should be false
67
+ end
68
+
69
+ Then /^I should not be able to hide the submission$/ do
70
+ @submission.hide.should be false
71
+ end
72
+
73
+ Then /^I should not be able to unhide the submission$/ do
74
+ @submission.unhide.should be false
75
+ end
76
+
77
+ Then /^I should be able to save the submission$/ do
78
+ @submission.save.should be true
79
+ end
80
+
81
+ Then /^I should be able to unsave the submission$/ do
82
+ @submission.unsave.should be true
83
+ end
84
+
85
+ Then /^I should be able to hide the submission$/ do
86
+ result = @submission.hide
87
+ @submission.unhide if result
88
+ result.should be true
89
+ end
90
+
91
+ Then /^I should be able to unhide the submission$/ do
92
+ @submission.unhide.should be true
93
+ end
94
+
95
+ Then /^I should be able to report the submission$/ do
96
+ @submission.report.should be true
97
+ end
98
+
99
+ Then /^I should not be able to report the submission$/ do
100
+ @submission.report.should be false
101
+ end
102
+
103
+ Then /^I should be able to see more comments if needed$/ do
104
+ pending
105
+ end
106
+
107
+ Then /^I should be able to moderator distinguish the submission$/ do
108
+ @submission.moderator_distinguish
109
+ end
110
+
111
+ Then /^I should be able to admin distinguish the submission$/ do
112
+ @submission.admin_distinguish
113
+ end
114
+
115
+ Then /^I should be able to indistinguish the submission$/ do
116
+ @submission.indistinguish
117
+ end
@@ -0,0 +1,25 @@
1
+ Before do
2
+ load_server_config
3
+ Reddit::Api.base_uri @address
4
+ Reddit::Submission.base_uri @address
5
+ Reddit::Comment.base_uri @address
6
+ Reddit::User.base_uri @address
7
+ @api = Reddit::Api.new @user, @pass
8
+ @api.login
9
+ end
10
+
11
+ Given /^I select a redditor$/ do
12
+ @submission = @api.browse("reddit_test1")[0]
13
+ @user = @submission.author
14
+ end
15
+
16
+ Then /^I should be able to friend them$/ do
17
+ @user.friend.should be true
18
+ end
19
+
20
+ Then /^I should be able to unfriend them$/ do
21
+ @user.unfriend.should be true
22
+ end
23
+
24
+
25
+
@@ -0,0 +1,58 @@
1
+ Feature: Submissions
2
+ I want to be able to peruse the submission details
3
+ And I want to be able to up vote the submission
4
+ And I want to be able to down vote the submission
5
+ And I want to be able to save submissions I like
6
+ And I want to be able to unsave submissions
7
+
8
+
9
+ Scenario: Viewing a submission
10
+ Scenario: When not logged in
11
+ Given I have a submission
12
+ And I'm not logged in
13
+ Then I should be able to see the author
14
+ And I should be able to see the title
15
+ And I should be able to see the selftext
16
+ And I should be able to see the url
17
+ And I should be able to see the up votes
18
+ And I should be able to see the down votes
19
+ And I should be able to see the comments
20
+ But I should not be able to upvote it
21
+ But I should not be able to downvote it
22
+ But I should not be able to save the submission
23
+ But I should not be able to unsave the submission
24
+ But I should not be able to hide the submission
25
+ But I should not be able to unhide the submission
26
+ But I should not be able to report the submission
27
+ And I should be able to see more comments if needed
28
+
29
+ Scenario: When logged in
30
+ Given I have a submission
31
+ And I'm logged in
32
+ Then I should be able to see the author
33
+ And I should be able to see the title
34
+ And I should be able to see the selftext
35
+ And I should be able to see the url
36
+ And I should be able to see the up votes
37
+ And I should be able to see the down votes
38
+ And I should be able to see the comments
39
+ And I should be able to upvote it
40
+ And I should be able to downvote it
41
+ And I should be able to save the submission
42
+ And I should be able to unsave the submission
43
+ And I should be able to hide the submission
44
+ And I should be able to unhide the submission
45
+ And I should be able to report the submission
46
+ And I should be able to see more comments if needed
47
+
48
+ Scenario: I want to moderator distinguish a submission
49
+ Given I have a submission
50
+ Then I should be able to moderator distinguish the submission
51
+
52
+ Scenario: I want to admin distinguish a submission
53
+ Given I have a submission
54
+ Then I should be able to admin distinguish the submission
55
+
56
+ Scenario: I want to indistinguish a submission
57
+ Given I have a submission
58
+ Then I should be able to indistinguish the submission
@@ -0,0 +1,17 @@
1
+ module BaseHelpers
2
+ def load_server_config
3
+ @address, @post, @user, @pass = parse_config.compact
4
+ end
5
+
6
+ protected
7
+ def parse_config
8
+ file = File.exist?("features/reddit.yml") ? YAML.load_file("features/reddit.yml") : {}
9
+ server = file.fetch("server"){ server_defaults }
10
+ return [ server["address"], server["port"], server["test_user"], server["test_pass"] ]
11
+ end
12
+
13
+ def server_defaults
14
+ {"address" => "reddit.local", "port" => "80", "test_user" => "reddit", "test_pass" => "password"}
15
+ end
16
+ end
17
+ World(BaseHelpers)
@@ -0,0 +1,11 @@
1
+ @user
2
+ Feature: User
3
+ In order have friends
4
+ As a Redditor
5
+ I want to be able to add and remove them
6
+
7
+ Scenario: Valid user and password
8
+ Given I select a redditor
9
+ Then I should be able to friend them
10
+ And I should be able to unfriend them
11
+
@@ -0,0 +1,17 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ module Reddit
4
+ end
5
+
6
+ require "httparty"
7
+ require "json"
8
+ require "reddit/version"
9
+ require "reddit/base"
10
+ require "reddit/json_listing"
11
+ require "reddit/api"
12
+ require "reddit/user"
13
+ require "reddit/vote"
14
+ require "reddit/submission"
15
+ require "reddit/comment"
16
+ require "reddit/message"
17
+
@@ -0,0 +1,46 @@
1
+ module Reddit
2
+
3
+ class Api < Base
4
+ attr_reader :last_action, :debug
5
+
6
+ def initialize(user=nil,password=nil, options={})
7
+ @user = user
8
+ @password = password
9
+ @debug = StringIO.new
10
+ end
11
+
12
+ def inspect
13
+ "<Reddit::Api user='#{user}'>"
14
+ end
15
+
16
+ def browse(subreddit, options={})
17
+ subreddit = sanitize_subreddit(subreddit)
18
+ options.merge! :handler => "Submission"
19
+ if options[:limit]
20
+ options.merge!({:query => {:limit => options[:limit]}})
21
+ end
22
+ read("/r/#{subreddit}.json", options )
23
+ end
24
+
25
+ def sent_messages
26
+ messages :sent
27
+ end
28
+
29
+ def received_messages
30
+ messages :inbox
31
+ end
32
+
33
+ def comments
34
+ messages :comments
35
+ end
36
+
37
+ def post_replies
38
+ messages :selfreply
39
+ end
40
+
41
+ protected
42
+ def messages(kind)
43
+ read("/message/#{kind.to_s}.json", :handler => "Message")
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,109 @@
1
+ module Reddit
2
+ class Base
3
+ include HTTParty
4
+
5
+ attr_reader :last_action, :debug
6
+ base_uri "www.reddit.com"
7
+ class << self; attr_reader :cookie, :modhash, :user_id, :user, end
8
+
9
+ def initialize(options={})
10
+ @debug = StringIO.new
11
+ end
12
+
13
+ def inspect
14
+ "<Reddit::Base user='#{user}'>"
15
+ end
16
+
17
+ def login
18
+ capture_session(self.class.post( "/api/login", {:body => {:user => @user, :passwd => @password}, :debug_output => @debug} ) )
19
+ logged_in?
20
+ end
21
+
22
+ def logout
23
+ Reddit::Base.instance_variable_set("@cookie",nil)
24
+ end
25
+
26
+ def cookie
27
+ Reddit::Base.cookie
28
+ end
29
+
30
+ def modhash
31
+ Reddit::Base.modhash
32
+ end
33
+
34
+ def user_id
35
+ Reddit::Base.user_id
36
+ end
37
+
38
+ def user
39
+ Reddit::Base.user
40
+ end
41
+
42
+ def logged_in?
43
+ !!(cookie && (cookie =~ /reddit_session/) != nil)
44
+ end
45
+
46
+ def user_agent
47
+ self.class.user_agent
48
+ end
49
+
50
+ def base_headers
51
+ self.class.base_headers
52
+ end
53
+
54
+ def read(url, options={})
55
+ unless throttled?
56
+ @debug.rewind
57
+ verb = (options[:verb] || "get")
58
+ param_key = (verb == "get") ? :query : :body
59
+ resp = self.class.send( verb, url, {param_key => (options[param_key] || {}), :headers => base_headers, :debug_output => @debug})
60
+ if valid_response?(resp)
61
+ @last_action = Time.now
62
+ klass = Reddit.const_get(options[:handler] || "Submission")
63
+ resp = klass.parse( JSON.parse(resp.body, :max_nesting => 9_999) )
64
+ return resp
65
+ else
66
+ return false
67
+ end
68
+ end
69
+ end
70
+
71
+ protected
72
+ def valid_response?(response)
73
+ response.code == 200 && response.headers["content-type"].to_s =~ /json/
74
+ end
75
+
76
+ def capture_session(response)
77
+ cookies = response.headers["set-cookie"]
78
+ Reddit::Base.instance_variable_set("@cookie", cookies)
79
+ Reddit::Base.instance_variable_set("@user", @user)
80
+ end
81
+
82
+ def capture_user_id
83
+ return true if user_id
84
+ this_user = read("/user/#{user}/about.json", :handler => "User")
85
+ Reddit::Base.instance_variable_set("@user_id", this_user.id)
86
+ end
87
+
88
+ def throttled?
89
+ @last_action && ( ( Time.now - @last_action ) < 1.0 )
90
+ end
91
+
92
+ def sanitize_subreddit(subreddit)
93
+ subreddit.gsub!(/^\/?r\//,'')
94
+ subreddit.gsub!(/\.json\Z/,'')
95
+ subreddit
96
+ end
97
+
98
+ class << self
99
+
100
+ def base_headers
101
+ {'Cookie' => Reddit::Base.cookie.to_s, 'user-agent' => user_agent}
102
+ end
103
+
104
+ def user_agent
105
+ "Ruby Reddit Client v#{Reddit::VERSION}"
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,86 @@
1
+ module Reddit
2
+ class Comment < Api
3
+ include JsonListing
4
+ attr_reader :body, :subreddit_id, :name, :created, :downs, :author, :created_utc, :body_html, :link_id, :parent_id, :likes, :replies, :subreddit, :ups, :debug, :kind
5
+ def initialize(json)
6
+ parse(json)
7
+ @debug = StringIO.new
8
+ end
9
+
10
+ def inspect
11
+ "<Reddit::Comment author='#{@author}' body='#{short_body}'>"
12
+ end
13
+
14
+ def id
15
+ "#{kind}_#{@id}"
16
+ end
17
+
18
+ def author
19
+ @author_data ||= read("/user/#{@author}/about.json", :handler => "User")
20
+ end
21
+
22
+ def to_s
23
+ body
24
+ end
25
+
26
+ def edit(newtext)
27
+ resp=self.class.post("/api/editusertext", {:body => {:thing_id => id, :uh => modhash, :r => subreddit, :text => newtext }, :headers => base_headers, :debug_output => @debug })
28
+ resp.code == 200
29
+ end
30
+
31
+ def hide # soft delete?
32
+ resp=self.class.post("/api/del", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => "removed" }, :headers => base_headers, :debug_output => @debug })
33
+ resp.code == 200
34
+ end
35
+
36
+ def remove
37
+ resp=self.class.post("/api/remove", {:body => {:id => id, :uh => modhash, :r => subreddit}, :headers => base_headers, :debug_output => @debug })
38
+ resp.code == 200
39
+ end
40
+
41
+ def approve
42
+ resp=self.class.post("/api/approve", {:body => {:id => id, :uh => modhash, :r => subreddit}, :headers => base_headers, :debug_output => @debug })
43
+ resp.code == 200
44
+ end
45
+
46
+ def moderator_distinguish
47
+ add_distinction "yes"
48
+ end
49
+
50
+ def admin_distinguish
51
+ add_distinction "admin"
52
+ end
53
+
54
+ def indistinguish
55
+ add_distinction "no"
56
+ end
57
+
58
+ def reply(text)
59
+ resp = self.class.post("/api/comment", {:body => {:thing_id => id, :text => text, :uh => modhash, :r => subreddit }, :headers => base_headers, :debug_output => @debug })
60
+ resp.code == 200
61
+ end
62
+
63
+ def upvote
64
+ Vote.new(self).up
65
+ end
66
+
67
+ def downvote
68
+ Vote.new(self).down
69
+ end
70
+
71
+ def short_body
72
+ str = body.to_s
73
+ if str.size > 15
74
+ str[0..15] + "..."
75
+ else
76
+ body
77
+ end
78
+ end
79
+
80
+ def add_distinction(verb)
81
+ resp=self.class.post("/api/distinguish/#{verb}", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => "distinguishing..."}, :headers => base_headers, :debug_output => @debug })
82
+ puts resp.headers
83
+ resp.code == 200
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,38 @@
1
+ module Reddit
2
+ module JsonListing
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ base.send(:include, InstanceMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def parse(json)
10
+ results = []
11
+ if json.is_a?(Array)
12
+ json.each do |j|
13
+ results << parse(j)
14
+ end
15
+ else
16
+ data = json["data"]
17
+ Reddit::Base.instance_variable_set("@modhash", data["modhash"]) # Needed for api calls
18
+
19
+ children = data["children"]
20
+ children.each do |message|
21
+ kind = message["kind"]
22
+ message["data"]["kind"] = kind
23
+ results << self.new(message["data"])
24
+ end
25
+ end
26
+
27
+ return results.flatten
28
+ end
29
+ end
30
+ module InstanceMethods
31
+ def parse(json)
32
+ json.keys.each do |key|
33
+ instance_variable_set("@#{key}", json[key])
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ module Reddit
2
+ class Message < Base
3
+ include JsonListing
4
+ attr_reader :body, :was_comment, :kind, :first_message, :name, :created, :dest, :created_utc, :body_html, :subreddit, :parent_id, :context, :replies, :subject, :debug
5
+ def initialize(json)
6
+ parse(json)
7
+ @debug = StringIO.new
8
+ end
9
+
10
+ def id
11
+ "#{kind}_#{@id}"
12
+ end
13
+
14
+ def author
15
+ @author_data ||= read("/user/#{@author}/about.json", :handler => "User")
16
+ end
17
+
18
+ def inspect
19
+ "<Reddit::Message '#{short_body}'>"
20
+ end
21
+
22
+ def short_body
23
+ if body.size > 15
24
+ body[0..15]
25
+ else
26
+ body
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,99 @@
1
+ module Reddit
2
+ class Submission < Base
3
+ include JsonListing
4
+ attr_reader :domain, :media_embed, :subreddit, :selftext_html, :selftext, :likes, :saved, :clicked, :media, :score, :over_18, :hidden, :thumbnail, :subreddit_id, :downs, :is_self, :permalink, :name, :created, :url, :title, :created_utc, :num_comments, :ups, :kind, :last_comment_id
5
+
6
+ def initialize(data)
7
+ parse(data)
8
+ @debug = StringIO.new
9
+ end
10
+
11
+ def inspect
12
+ "<Reddit::Submission id='#{id}' author='#{@author}' title='#{title}'>"
13
+ end
14
+
15
+ def id
16
+ "#{kind}_#{@id}"
17
+ end
18
+
19
+ def author
20
+ @author_data ||= read("/user/#{@author}/about.json", :handler => "User")
21
+ end
22
+
23
+ def add_comment(text)
24
+ resp = self.class.post("/api/comment", {:body => {:thing_id => id, :text => text, :uh => modhash, :r => subreddit }, :headers => base_headers, :debug_output => @debug })
25
+ resp.code == 200
26
+ end
27
+
28
+ def upvote
29
+ Reddit::Vote.new(self).up
30
+ end
31
+
32
+ def downvote
33
+ Reddit::Vote.new(self).down
34
+ end
35
+
36
+ def save
37
+ toggle :save
38
+ end
39
+
40
+ def unsave
41
+ toggle :unsave
42
+ end
43
+
44
+ def hide
45
+ toggle :hide
46
+ end
47
+
48
+ def unhide
49
+ toggle :unhide
50
+ end
51
+
52
+ def report
53
+ toggle :report
54
+ end
55
+
56
+ def moderator_distinguish
57
+ add_distinction "yes"
58
+ end
59
+
60
+ def admin_distinguish
61
+ add_distinction "admin"
62
+ end
63
+
64
+ def indistinguish
65
+ add_distinction "no"
66
+ end
67
+
68
+ def comments(more=false)
69
+ #TODO Get morechildren to work correctly
70
+ if more && last_comment_id
71
+ opts = {:handler => "Comment",
72
+ :verb => "post",
73
+ :body =>
74
+ {:link_id => last_comment_id, :depth => 0, :r => subreddit, :uh => modhash, :renderstyle => "json", :pv_hex => "", :id => id}
75
+ }
76
+ return read("/api/morechildren", opts )
77
+
78
+ else
79
+ _comments = read( permalink + ".json", {:handler => "Comment", :query => {:limit => 50}} )
80
+ @last_comment_id = _comments.last.id if _comments && _comments.any?
81
+ return _comments
82
+ end
83
+ end
84
+
85
+ protected
86
+ def add_distinction(verb)
87
+ resp=self.class.post("/api/distinguish/#{verb}", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => "distinguishing..."}, :headers => base_headers, :debug_output => @debug })
88
+ resp.code == 200
89
+ end
90
+
91
+ def toggle(which)
92
+ return false unless logged_in?
93
+ mapping = {:save => "save", :unsave => "unsave", :hide => "hidden", :unhide => "unhidden", :report => "report"}
94
+ mode = mapping[which]
95
+ resp = self.class.post("/api/#{which}", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => mode }, :headers => base_headers, :debug_output => @debug })
96
+ resp.code == 200
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,47 @@
1
+
2
+ module Reddit
3
+ class User < Api
4
+ attr_reader :name, :debug, :created, :created_utc, :link_karma, :comment_karma, :is_mod, :has_mod_mail, :kind
5
+ def initialize(json)
6
+ @debug = StringIO.new
7
+ parse(json)
8
+ end
9
+
10
+ def inspect
11
+ "<Reddit::User name='#{name}'>"
12
+ end
13
+
14
+ def id
15
+ "#{kind}_#{@id}"
16
+ end
17
+
18
+ def to_s
19
+ name
20
+ end
21
+
22
+ def friend
23
+ capture_user_id
24
+ resp=self.class.post("/api/friend", {:body => {:name => name, :container => user_id, :type => "friend", :uh => modhash}, :headers => base_headers, :debug_output => @debug })
25
+ resp.code == 200
26
+ end
27
+
28
+ def unfriend
29
+ capture_user_id
30
+ resp=self.class.post("/api/unfriend", {:body => {:name => name, :container => user_id, :type => "friend", :uh => modhash}, :headers => base_headers, :debug_output => @debug })
31
+ resp.code == 200
32
+ end
33
+
34
+ protected
35
+ def parse(json)
36
+ json.keys.each do |key|
37
+ instance_variable_set("@#{key}", json[key])
38
+ end
39
+ end
40
+
41
+ def self.parse(json)
42
+ kind, data = json["kind"], json["data"]
43
+ data["kind"] = kind
44
+ return self.new(data)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module Reddit
2
+ VERSION = File.exist?("VERSION") ? File.read("VERSION").chomp : ""
3
+ end
@@ -0,0 +1,33 @@
1
+ module Reddit
2
+ class Vote < Base
3
+ attr_reader :submission
4
+
5
+ def initialize(submission)
6
+ @submission = submission
7
+ end
8
+
9
+ def up
10
+ vote(:up)
11
+ end
12
+
13
+ def down
14
+ vote(:down)
15
+ end
16
+
17
+ def inspect
18
+ "<Reddit::Vote>"
19
+ end
20
+
21
+ protected
22
+ def vote(direction)
23
+ return false unless logged_in?
24
+ up_or_down = direction == :up ? 1 : -1
25
+ resp = self.class.post( "/api/vote", {:body => {:id => submission.id, :dir => up_or_down, :uh => modhash}, :headers => base_headers})
26
+ if resp.code == 200
27
+ return true
28
+ else
29
+ return false
30
+ end
31
+ end
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_reddit_api
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 9
9
+ version: 0.1.9
10
+ platform: ruby
11
+ authors:
12
+ - James Cook
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-05 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: httparty
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: cucumber
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
46
+ description: Wraps many reddit API functions such as submission and comments browsing, voting, messaging, friending, and more.
47
+ email:
48
+ - jamecook@gmail.com
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ extra_rdoc_files: []
54
+
55
+ files:
56
+ - lib/ruby_reddit_api.rb
57
+ - lib/ruby_reddit_api/user.rb
58
+ - lib/ruby_reddit_api/comment.rb
59
+ - lib/ruby_reddit_api/message.rb
60
+ - lib/ruby_reddit_api/version.rb
61
+ - lib/ruby_reddit_api/vote.rb
62
+ - lib/ruby_reddit_api/submission.rb
63
+ - lib/ruby_reddit_api/api.rb
64
+ - lib/ruby_reddit_api/json_listing.rb
65
+ - lib/ruby_reddit_api/base.rb
66
+ - README
67
+ - features/reddit.yml
68
+ - features/submission.feature
69
+ - features/comment.feature
70
+ - features/user.feature
71
+ - features/base.feature
72
+ - features/message.feature
73
+ - features/api.feature
74
+ - features/step_definitions/message_steps.rb
75
+ - features/step_definitions/submission_steps.rb
76
+ - features/step_definitions/api_steps.rb
77
+ - features/step_definitions/user_steps.rb
78
+ - features/step_definitions/comment_steps.rb
79
+ - features/step_definitions/base_steps.rb
80
+ - features/support/base_helpers.rb
81
+ has_rdoc: true
82
+ homepage: http://github.com/jamescook/RubyRedditAPI
83
+ licenses: []
84
+
85
+ post_install_message:
86
+ rdoc_options: []
87
+
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 1
105
+ - 3
106
+ - 6
107
+ version: 1.3.6
108
+ requirements: []
109
+
110
+ rubyforge_project:
111
+ rubygems_version: 1.3.7
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Wrapper for reddit API
115
+ test_files:
116
+ - features/reddit.yml
117
+ - features/submission.feature
118
+ - features/comment.feature
119
+ - features/user.feature
120
+ - features/base.feature
121
+ - features/message.feature
122
+ - features/api.feature
123
+ - features/step_definitions/message_steps.rb
124
+ - features/step_definitions/submission_steps.rb
125
+ - features/step_definitions/api_steps.rb
126
+ - features/step_definitions/user_steps.rb
127
+ - features/step_definitions/comment_steps.rb
128
+ - features/step_definitions/base_steps.rb
129
+ - features/support/base_helpers.rb