ruby_reddit_api 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,6 +1,6 @@
1
- Ruby Reddit Client v0.1.9
1
+ Ruby Reddit Client v0.2.0
2
2
  ==================
3
- Tested with 1.9.2
3
+ Tested with ruby 1.9.2
4
4
 
5
5
  Usage:
6
6
  =======
@@ -12,9 +12,10 @@ Usage:
12
12
  Features:
13
13
  ========
14
14
  - Authentication
15
- - Parse submissions
16
- - Comments parsing
17
- - Vote on submission
15
+ - Browse submissions
16
+ - Read comments
17
+ - Friend/unfriend redditors
18
+ - Comment & submission voting
18
19
 
19
20
 
20
21
  Running Tests:
@@ -1,5 +1,6 @@
1
1
  module Reddit
2
2
 
3
+ # @author James Cook
3
4
  class Api < Base
4
5
  attr_reader :last_action, :debug
5
6
 
@@ -13,6 +14,9 @@ module Reddit
13
14
  "<Reddit::Api user='#{user}'>"
14
15
  end
15
16
 
17
+ # Browse submissions by subreddit
18
+ # @param [String] Subreddit to browse
19
+ # @return [Array<Reddit::Submission>]
16
20
  def browse(subreddit, options={})
17
21
  subreddit = sanitize_subreddit(subreddit)
18
22
  options.merge! :handler => "Submission"
@@ -22,18 +26,26 @@ module Reddit
22
26
  read("/r/#{subreddit}.json", options )
23
27
  end
24
28
 
29
+ # Read sent messages
30
+ # @return [Array<Reddit::Message>]
25
31
  def sent_messages
26
32
  messages :sent
27
33
  end
28
34
 
35
+ # Read received messages
36
+ # @return [Array<Reddit::Message>]
29
37
  def received_messages
30
38
  messages :inbox
31
39
  end
32
40
 
41
+ # Read received comments
42
+ # @return [Array<Reddit::Message>]
33
43
  def comments
34
44
  messages :comments
35
45
  end
36
46
 
47
+ # Read post replies
48
+ # @return [Array<Reddit::Message>]
37
49
  def post_replies
38
50
  messages :selfreply
39
51
  end
@@ -1,4 +1,7 @@
1
1
  module Reddit
2
+ # Base module all other classes descend from. Stores the cookie, modhash and user info for many API calls. Handles authentication and directs JSON
3
+ # to the relevant handler.
4
+ # @author James Cook
2
5
  class Base
3
6
  include HTTParty
4
7
 
@@ -10,47 +13,66 @@ module Reddit
10
13
  @debug = StringIO.new
11
14
  end
12
15
 
16
+ # @return [String]
13
17
  def inspect
14
18
  "<Reddit::Base user='#{user}'>"
15
19
  end
16
20
 
21
+ # Login to Reddit and capture the cookie
22
+ # @return [Boolean] Login success or failure
17
23
  def login
18
24
  capture_session(self.class.post( "/api/login", {:body => {:user => @user, :passwd => @password}, :debug_output => @debug} ) )
19
25
  logged_in?
20
26
  end
21
27
 
28
+ # Remove the cookie to effectively logout of Reddit
29
+ # @return [nil]
22
30
  def logout
23
31
  Reddit::Base.instance_variable_set("@cookie",nil)
24
32
  end
25
33
 
34
+ # @return [String, nil]
26
35
  def cookie
27
36
  Reddit::Base.cookie
28
37
  end
29
38
 
39
+ # A kind of authenticity token for many API calls
40
+ # @return [String, nil]
30
41
  def modhash
31
42
  Reddit::Base.modhash
32
43
  end
33
44
 
45
+ # Reddit's displayed ID for the logged in user
46
+ # @return [String]
34
47
  def user_id
35
48
  Reddit::Base.user_id
36
49
  end
37
50
 
51
+ # Logged in user
52
+ # @return [String]
38
53
  def user
39
54
  Reddit::Base.user
40
55
  end
41
56
 
57
+ # The session is authenticated if the captured cookie shows a valid session is in place
58
+ # @return [true,false]
42
59
  def logged_in?
43
60
  !!(cookie && (cookie =~ /reddit_session/) != nil)
44
61
  end
45
62
 
63
+ # @return String
46
64
  def user_agent
47
65
  self.class.user_agent
48
66
  end
49
67
 
68
+ # HTTP headers to be sent in all API requests. At a minimum, 'User-agent' and 'Cookie' are needed.
69
+ # @return Hash
50
70
  def base_headers
51
71
  self.class.base_headers
52
72
  end
53
73
 
74
+ # Base communication function for nearly all API calls
75
+ # @return [Reddit::Submission, Reddit::Comment, Reddit::User, false] Various reddit-related, json parseable objects
54
76
  def read(url, options={})
55
77
  unless throttled?
56
78
  @debug.rewind
@@ -1,5 +1,7 @@
1
1
  module Reddit
2
- class Comment < Api
2
+ # @author James Cook
3
+ class Comment < Thing
4
+
3
5
  include JsonListing
4
6
  attr_reader :body, :subreddit_id, :name, :created, :downs, :author, :created_utc, :body_html, :link_id, :parent_id, :likes, :replies, :subreddit, :ups, :debug, :kind
5
7
  def initialize(json)
@@ -11,33 +13,34 @@ module Reddit
11
13
  "<Reddit::Comment author='#{@author}' body='#{short_body}'>"
12
14
  end
13
15
 
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
-
16
+ # @return [String]
22
17
  def to_s
23
18
  body
24
19
  end
25
20
 
21
+ # Modify a comment
22
+ # @return [true,false]
26
23
  def edit(newtext)
27
24
  resp=self.class.post("/api/editusertext", {:body => {:thing_id => id, :uh => modhash, :r => subreddit, :text => newtext }, :headers => base_headers, :debug_output => @debug })
28
25
  resp.code == 200
29
26
  end
30
27
 
31
- def hide # soft delete?
28
+ # Hide a comment
29
+ # @return [true,false]
30
+ def hide
32
31
  resp=self.class.post("/api/del", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => "removed" }, :headers => base_headers, :debug_output => @debug })
33
32
  resp.code == 200
34
33
  end
35
34
 
35
+ # Remove a comment
36
+ # @return [true,false]
36
37
  def remove
37
38
  resp=self.class.post("/api/remove", {:body => {:id => id, :uh => modhash, :r => subreddit}, :headers => base_headers, :debug_output => @debug })
38
39
  resp.code == 200
39
40
  end
40
41
 
42
+ # Approve a comment
43
+ # @return [true,false]
41
44
  def approve
42
45
  resp=self.class.post("/api/approve", {:body => {:id => id, :uh => modhash, :r => subreddit}, :headers => base_headers, :debug_output => @debug })
43
46
  resp.code == 200
@@ -55,19 +58,15 @@ module Reddit
55
58
  add_distinction "no"
56
59
  end
57
60
 
61
+ # Reply to another comment
62
+ # @return [true,false]
58
63
  def reply(text)
59
64
  resp = self.class.post("/api/comment", {:body => {:thing_id => id, :text => text, :uh => modhash, :r => subreddit }, :headers => base_headers, :debug_output => @debug })
60
65
  resp.code == 200
61
66
  end
62
67
 
63
- def upvote
64
- Vote.new(self).up
65
- end
66
-
67
- def downvote
68
- Vote.new(self).down
69
- end
70
-
68
+ # Trimmed comment body suitable for #inspect
69
+ # @return [String]
71
70
  def short_body
72
71
  str = body.to_s
73
72
  if str.size > 15
@@ -1,3 +1,4 @@
1
+ #@author James Cook
1
2
  module Reddit
2
3
  module JsonListing
3
4
  def self.included(base)
@@ -6,6 +7,9 @@ module Reddit
6
7
  end
7
8
 
8
9
  module ClassMethods
10
+
11
+ # @param [Hash] JSON received from Reddit
12
+ # @return [Array<Reddit::Submission, Reddit::User, Reddit::Comment, Reddit::Message>]
9
13
  def parse(json)
10
14
  results = []
11
15
  if json.is_a?(Array)
@@ -28,10 +32,14 @@ module Reddit
28
32
  end
29
33
  end
30
34
  module InstanceMethods
35
+ # Iterate over JSON and set instance variables that map to each JSON key
36
+ # @param [Hash] JSON received from Reddit
37
+ # @return [true]
31
38
  def parse(json)
32
39
  json.keys.each do |key|
33
40
  instance_variable_set("@#{key}", json[key])
34
41
  end
42
+ true
35
43
  end
36
44
  end
37
45
  end
@@ -1,16 +1,22 @@
1
+ # @author James Cook
1
2
  module Reddit
2
3
  class Message < Base
3
4
  include JsonListing
5
+
4
6
  attr_reader :body, :was_comment, :kind, :first_message, :name, :created, :dest, :created_utc, :body_html, :subreddit, :parent_id, :context, :replies, :subject, :debug
5
7
  def initialize(json)
6
8
  parse(json)
7
9
  @debug = StringIO.new
8
10
  end
9
11
 
12
+ # The reddit ID of this message
13
+ # @return [String]
10
14
  def id
11
15
  "#{kind}_#{@id}"
12
16
  end
13
17
 
18
+ # The author of the message. The data is lazy-loaded and cached on the message
19
+ # @return [Reddit::User]
14
20
  def author
15
21
  @author_data ||= read("/user/#{@author}/about.json", :handler => "User")
16
22
  end
@@ -19,6 +25,8 @@ module Reddit
19
25
  "<Reddit::Message '#{short_body}'>"
20
26
  end
21
27
 
28
+ # Trimmed comment body suitable for #inspect
29
+ # @return [String]
22
30
  def short_body
23
31
  if body.size > 15
24
32
  body[0..15]
@@ -1,58 +1,45 @@
1
+ # @author James Cook
1
2
  module Reddit
2
- class Submission < Base
3
+ class Submission < Thing
3
4
  include JsonListing
4
5
  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
 
6
- def initialize(data)
7
- parse(data)
8
- @debug = StringIO.new
9
- end
10
-
11
7
  def inspect
12
8
  "<Reddit::Submission id='#{id}' author='#{@author}' title='#{title}'>"
13
9
  end
14
10
 
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
-
11
+ # Add a comment to a submission
12
+ # @param [String] Comment text
13
+ # @return [true,false]
23
14
  def add_comment(text)
24
15
  resp = self.class.post("/api/comment", {:body => {:thing_id => id, :text => text, :uh => modhash, :r => subreddit }, :headers => base_headers, :debug_output => @debug })
25
16
  resp.code == 200
26
17
  end
27
18
 
28
- def upvote
29
- Reddit::Vote.new(self).up
30
- end
31
-
32
- def downvote
33
- Reddit::Vote.new(self).down
34
- end
35
-
19
+ # Save submission
20
+ # @return [true,false]
36
21
  def save
37
22
  toggle :save
38
23
  end
39
24
 
25
+ # Unsave submission
26
+ # @return [true,false]
40
27
  def unsave
41
28
  toggle :unsave
42
29
  end
43
30
 
31
+ # Hide submission
32
+ # @return [true,false]
44
33
  def hide
45
34
  toggle :hide
46
35
  end
47
36
 
37
+ # Unhide submission
38
+ # @return [true,false]
48
39
  def unhide
49
40
  toggle :unhide
50
41
  end
51
42
 
52
- def report
53
- toggle :report
54
- end
55
-
56
43
  def moderator_distinguish
57
44
  add_distinction "yes"
58
45
  end
@@ -65,6 +52,9 @@ module Reddit
65
52
  add_distinction "no"
66
53
  end
67
54
 
55
+ # Fetch submission comments
56
+ # @todo Move to 'Thing' class
57
+ # @return [Array<Reddit::Comment>]
68
58
  def comments(more=false)
69
59
  #TODO Get morechildren to work correctly
70
60
  if more && last_comment_id
@@ -87,13 +77,5 @@ module Reddit
87
77
  resp=self.class.post("/api/distinguish/#{verb}", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => "distinguishing..."}, :headers => base_headers, :debug_output => @debug })
88
78
  resp.code == 200
89
79
  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
80
  end
99
81
  end
@@ -0,0 +1,49 @@
1
+ module Reddit
2
+ # @author James Cook
3
+ class Thing < Base
4
+ include JsonListing
5
+
6
+ def initialize(data)
7
+ parse(data)
8
+ @debug = StringIO.new
9
+ end
10
+
11
+ # The reddit ID of this entity
12
+ # @return [String]
13
+ def id
14
+ "#{kind}_#{@id}"
15
+ end
16
+
17
+ # The author of the entity. The data is lazy-loaded and cached on the object
18
+ # @return [Reddit::User]
19
+ def author
20
+ @author_data ||= read("/user/#{@author}/about.json", :handler => "User")
21
+ end
22
+
23
+ # Upvote thing
24
+ # @return [true,false]
25
+ def upvote
26
+ Reddit::Vote.new(self).up
27
+ end
28
+
29
+ # Downvote thing
30
+ # @return [true,false]
31
+ def downvote
32
+ Reddit::Vote.new(self).down
33
+ end
34
+
35
+ # Report thing
36
+ # @return [true,false]
37
+ def report
38
+ toggle :report
39
+ end
40
+
41
+ def toggle(which)
42
+ return false unless logged_in?
43
+ mapping = {:save => "save", :unsave => "unsave", :hide => "hidden", :unhide => "unhidden", :report => "report"}
44
+ mode = mapping[which]
45
+ resp = self.class.post("/api/#{which}", {:body => {:id => id, :uh => modhash, :r => subreddit, :executed => mode }, :headers => base_headers, :debug_output => @debug })
46
+ resp.code == 200
47
+ end
48
+ end
49
+ end
@@ -1,6 +1,7 @@
1
-
2
1
  module Reddit
2
+ # @author James Cook
3
3
  class User < Api
4
+ include JSONListing
4
5
  attr_reader :name, :debug, :created, :created_utc, :link_karma, :comment_karma, :is_mod, :has_mod_mail, :kind
5
6
  def initialize(json)
6
7
  @debug = StringIO.new
@@ -11,37 +12,31 @@ module Reddit
11
12
  "<Reddit::User name='#{name}'>"
12
13
  end
13
14
 
15
+ # The reddit ID of this submission
16
+ # @return [String]
14
17
  def id
15
18
  "#{kind}_#{@id}"
16
19
  end
17
20
 
21
+ # @return [String]
18
22
  def to_s
19
23
  name
20
24
  end
21
25
 
26
+ # Add redditor as friend. Requires a authenticated user.
27
+ # @return [true,false]
22
28
  def friend
23
29
  capture_user_id
24
30
  resp=self.class.post("/api/friend", {:body => {:name => name, :container => user_id, :type => "friend", :uh => modhash}, :headers => base_headers, :debug_output => @debug })
25
31
  resp.code == 200
26
32
  end
27
33
 
34
+ # Remove redditor as friend. Requires a authenticated user.
35
+ # @return [true,false]
28
36
  def unfriend
29
37
  capture_user_id
30
38
  resp=self.class.post("/api/unfriend", {:body => {:name => name, :container => user_id, :type => "friend", :uh => modhash}, :headers => base_headers, :debug_output => @debug })
31
39
  resp.code == 200
32
40
  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
41
  end
47
42
  end
@@ -1,3 +1,6 @@
1
+ # @author James Cook
1
2
  module Reddit
3
+ # Capture the code version from the VERSION file
4
+ # @return [String]
2
5
  VERSION = File.exist?("VERSION") ? File.read("VERSION").chomp : ""
3
6
  end
@@ -1,3 +1,4 @@
1
+ # @author James Cook
1
2
  module Reddit
2
3
  class Vote < Base
3
4
  attr_reader :submission
@@ -6,14 +7,19 @@ module Reddit
6
7
  @submission = submission
7
8
  end
8
9
 
10
+ # Upvote submission or comment
11
+ # @return [true,false]
9
12
  def up
10
13
  vote(:up)
11
14
  end
12
15
 
16
+ # Downvote submission or comment
17
+ # @return [true,false]
13
18
  def down
14
19
  vote(:down)
15
20
  end
16
21
 
22
+ #@return [String]
17
23
  def inspect
18
24
  "<Reddit::Vote>"
19
25
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 9
9
- version: 0.1.9
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - James Cook
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-05 00:00:00 -04:00
17
+ date: 2010-10-06 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -54,6 +54,7 @@ extra_rdoc_files: []
54
54
 
55
55
  files:
56
56
  - lib/ruby_reddit_api.rb
57
+ - lib/ruby_reddit_api/thing.rb
57
58
  - lib/ruby_reddit_api/user.rb
58
59
  - lib/ruby_reddit_api/comment.rb
59
60
  - lib/ruby_reddit_api/message.rb
@@ -78,7 +79,7 @@ files:
78
79
  - features/step_definitions/comment_steps.rb
79
80
  - features/step_definitions/base_steps.rb
80
81
  - features/support/base_helpers.rb
81
- has_rdoc: true
82
+ has_rdoc: false
82
83
  homepage: http://github.com/jamescook/RubyRedditAPI
83
84
  licenses: []
84
85