redd 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68ca6da5f545b524f8b03e08e6b493b3df260202
4
- data.tar.gz: 6358bd923e9c302160b7f4a9bb095d4691741d8b
3
+ metadata.gz: d85e07d35f21832e40d2a17c6063d758b2051171
4
+ data.tar.gz: d91adb52b18dd74a382369e5ff57384f27bc9cae
5
5
  SHA512:
6
- metadata.gz: 8bb2902ebe6c5e959e24fc8ba672be642acd35c90667ba3a35023e5fa69ec8336e3f51d6489133e9417377417012879f5954fe405580c17a422a5542bfee7adc
7
- data.tar.gz: c7f7c8816778a0c26aa7a49a8ffc514a64dcb22d3e1bb755856cbedb1888e7d6ee3946a0b396167328d090328f90dfbc9e290aa797145d110d7b4e6f42260326
6
+ metadata.gz: b1330d62998349feaa50b8a9266ba295145dfe0d633b290f77ecf72a5eadaba36733467d2e9c5138bc89fa9f7043b6616d28408384ce67832ca43db3500750d2
7
+ data.tar.gz: 64b1c5d48b6e8c34e4fa6eb0b28465766240955966d4ef5e4235276dce8d791f0a78cbc83109b8565e4a430e082394ee83902063e2ebb3a895af8489348e78db
data/.rspec CHANGED
@@ -1,2 +1,4 @@
1
1
  --color
2
- --format documentation
2
+ --warnings
3
+ --format documentation
4
+ --require spec_helper
data/README.md CHANGED
@@ -66,7 +66,7 @@ Ruby and redd make creating reddit bots accessible and fun. To demonstrate, let'
66
66
  time_left = e.time
67
67
  sleep(time_left)
68
68
  rescue Redd::Error => e
69
- status = e.message.status
69
+ status = e.code
70
70
  # 5-something errors are usually errors on reddit's end.
71
71
  raise e unless (500...600).include?(status)
72
72
  end
@@ -45,6 +45,10 @@ module Redd
45
45
  # @return [String] The site to connect to authenticate with.
46
46
  attr_accessor :auth_endpoint
47
47
 
48
+ def self.new_from_credentials(username, password, options = {})
49
+ Redd::Client::Unauthenticated.new.login(username, password, options)
50
+ end
51
+
48
52
  # Set up an authenticated connection to reddit.
49
53
  #
50
54
  # @param [String] cookie The cookie to use when sending a request.
@@ -68,20 +72,13 @@ module Redd
68
72
 
69
73
  private
70
74
 
71
- # Gets the Faraday connection or creates one if it doesn't exist yet.
72
- #
73
- # @return [Faraday] A new Faraday connection.
74
- def connection
75
- @connection ||= Faraday.new(url: api_endpoint) do |faraday|
76
- faraday.use Faraday::Request::UrlEncoded
77
- faraday.use Redd::Response::RaiseError
78
- faraday.use Redd::Response::ParseJson
79
- faraday.adapter Faraday.default_adapter
80
-
81
- faraday.headers["User-Agent"] = user_agent
82
- faraday.headers["Cookie"] = "reddit_session=#{cookie}"
83
- faraday.headers["X-Modhash"] = modhash
84
- end
75
+ # @return [Hash] The headers that are sent with every request.
76
+ def headers
77
+ @headers ||= {
78
+ "User-Agent" => @user_agent,
79
+ "Cookie" => "reddit_session=#{@cookie}",
80
+ "X-Modhash" => @modhash
81
+ }
85
82
  end
86
83
  end
87
84
  end
@@ -2,23 +2,42 @@ module Redd
2
2
  module Client
3
3
  class Authenticated
4
4
  module Flair
5
- def get_flair_list(subreddit = nil, params = {})
6
- name = extract_attribute(subreddit, :display_name) if subreddit
5
+ def get_flair_list(subreddit, params = {})
6
+ name = extract_attribute(subreddit, :display_name)
7
7
 
8
8
  path = "/api/flairlist.json"
9
- path = path.prepend("/r/#{name}") if name
9
+ path = path.prepend("/r/#{name}")
10
10
 
11
11
  get(path, params)[:users]
12
12
  end
13
13
 
14
14
  # @see http://ruby-doc.org/core-1.9.3/String.html#method-i-casecmp
15
- def get_flair(user, subreddit = nil)
15
+ def get_flair(subreddit, user)
16
16
  username = extract_attribute(user, :name)
17
17
  options = {name: username}
18
18
 
19
19
  flair = get_flair_list(subreddit, options).first
20
20
  flair if flair[:user].casecmp(username.downcase) == 0
21
21
  end
22
+
23
+ def set_flair(subreddit, user_or_link, text = "", css_class = "")
24
+ name = extract_attribute(subreddit, :display_name)
25
+
26
+ path = "/api/flair"
27
+ path = path.prepend("/r/#{name}")
28
+ params = {api_type: "json", text: text, css_class: css_class}
29
+
30
+ case user_or_link
31
+ when Redd::Object::User
32
+ params[:name] = extract_attribute(user_or_link, :name)
33
+ when Redd::Object::Submission
34
+ params[:link] = extract_attribute(user_or_link, :display_name)
35
+ else
36
+ fail "You should provide a User or Submission object."
37
+ end
38
+
39
+ post path, params
40
+ end
22
41
  end
23
42
  end
24
43
  end
@@ -2,8 +2,34 @@ module Redd
2
2
  module Client
3
3
  class Authenticated
4
4
  module LinksComments
5
+ def submit(
6
+ title, kind, text_or_url, captcha = nil, identifier = nil,
7
+ options = {}
8
+ )
9
+ # Set required parameters
10
+ params = {
11
+ api_type: "json", extension: "json", title: title, kind: kind
12
+ }
13
+
14
+ # Set url or selftext depending on kind
15
+ case kind.to_sym
16
+ when :self
17
+ params[:text] = text_or_url
18
+ when :link
19
+ params[:url] = text_or_url
20
+ end
21
+
22
+ # Optional captcha
23
+ params << {captcha: captcha, iden: identifier} if captcha
24
+
25
+ # Fill in the rest of the options
26
+ params << options
27
+
28
+ post "/api/submit", params
29
+ end
30
+
5
31
  # @todo return the edited object.
6
- def add_comment(thing, text, return_element = true)
32
+ def add_comment(thing, text)
7
33
  fullname = extract_fullname(thing)
8
34
  post "/api/comment", api_type: "json", text: text, thing_id: fullname
9
35
  end
@@ -57,6 +57,11 @@ module Redd
57
57
 
58
58
  private
59
59
 
60
+ # @return [Hash] The headers that are sent with every request.
61
+ def headers
62
+ @headers ||= {"User-Agent" => @user_agent}
63
+ end
64
+
60
65
  # Gets the Faraday connection or creates one if it doesn't exist yet.
61
66
  #
62
67
  # @return [Faraday] A new Faraday connection.
@@ -67,7 +72,7 @@ module Redd
67
72
  faraday.use Redd::Response::ParseJson
68
73
  faraday.adapter Faraday.default_adapter
69
74
 
70
- faraday.headers["User-Agent"] = user_agent
75
+ faraday.headers = headers
71
76
  end
72
77
  end
73
78
 
@@ -2,18 +2,15 @@ module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
4
  module Account
5
- def login(username, password, remember = false)
6
- meth = :post
7
- path = "/api/login"
8
- params = {
9
-
10
- }
5
+ def login(username, password, remember = false, options = {})
11
6
  response = post "/api/login",
12
7
  api_type: "json", user: username, passwd: password, rem: remember
13
8
  data = response[:json][:data]
14
9
 
15
10
  require "redd/client/authenticated"
16
- Redd::Client::Authenticated.new(data[:cookie], data[:modhash])
11
+ Redd::Client::Authenticated.new(
12
+ data[:cookie], data[:modhash], options
13
+ )
17
14
  end
18
15
  end
19
16
  end
@@ -5,10 +5,10 @@ module Redd
5
5
  # @note Reddit does accept a subreddit, but with fullnames and urls, I
6
6
  # assumed that was unnecessary.
7
7
  def get_info(params = {})
8
- object_from_response :get, "/api/info.json"
8
+ object_from_response :get, "/api/info.json", params
9
9
  end
10
10
 
11
- def get_comments(submission)
11
+ def submission_comments(submission)
12
12
  id = extract_id(submission)
13
13
  comments_from_response :get, "/comments/#{id}.json"
14
14
  end
@@ -19,24 +19,36 @@ module Redd
19
19
  object_from_body(replies)
20
20
  end
21
21
 
22
- # FIX THIS ASAP
23
- def replace_morecomments(morecomments)
22
+ def replace_morecomments(morecomments, submission = nil)
24
23
  parent_id = morecomments.parent_id
25
- link_id =
26
- if parent_id.start_with?("t1_")
27
- get_info(id: parent_id).first.link_id
24
+ link_id =
25
+ if submission
26
+ submission
28
27
  elsif parent_id.start_with?("t3_")
29
28
  parent_id
29
+ elsif parent_id.start_with?("t1_")
30
+ get_info(id: parent_id).first.link_id
30
31
  end
31
32
 
32
- meth = :post
33
- path = "/api/morechildren"
34
- params = {
35
- api_type: "json", link_id: link_id,
36
- children: morecomments.children.join(",")
37
- }
33
+ response = post "/api/morechildren", api_type: "json",
34
+ link_id: link_id, children: morecomments.children.join(",")
35
+ comments = response[:json][:data][:things]
36
+
37
+ # No idea how to increase the depth of the comments.
38
+ comments.select! { |comment| comment[:kind] == "t1" }
38
39
 
39
- send(meth, path, params)
40
+ comments.map do |comment|
41
+ object_from_body(
42
+ kind: comment[:kind],
43
+ data: {
44
+ parent_id: comment[:data][:parent],
45
+ body: comment[:data][:contentText],
46
+ body_html: comment[:data][:contentHTML],
47
+ link_id: comment[:data][:link],
48
+ name: comment[:data][:id]
49
+ }
50
+ )
51
+ end
40
52
  end
41
53
  end
42
54
  end
@@ -6,6 +6,7 @@ require "redd/object/private_message"
6
6
  require "redd/object/submission"
7
7
  require "redd/object/subreddit"
8
8
  require "redd/object/user"
9
+ require "redd/object/wiki_page"
9
10
 
10
11
  module Redd
11
12
  module Client
@@ -65,6 +66,8 @@ module Redd
65
66
  Redd::Object::PrivateMessage
66
67
  when "t5"
67
68
  Redd::Object::Subreddit
69
+ when "wikipage"
70
+ Redd::Object::WikiPage
68
71
  else
69
72
  Redd::Thing
70
73
  end
@@ -2,7 +2,17 @@ module Redd
2
2
  module Client
3
3
  class Unauthenticated
4
4
  module Wiki
5
-
5
+ def get_wikipages(subreddit = nil)
6
+ path = "/wiki/pages.json"
7
+ path.prepend("/r/#{subreddit}") if subreddit
8
+ get(path)[:data]
9
+ end
10
+
11
+ def wikipage(page, subreddit = nil, params = {})
12
+ path = "/wiki/#{page}.json"
13
+ path.prepend("/r/#{subreddit}") if subreddit
14
+ object_from_response :get, path, params
15
+ end
6
16
  end
7
17
  end
8
18
  end
data/lib/redd/error.rb CHANGED
@@ -1,5 +1,16 @@
1
1
  module Redd
2
2
  class Error < StandardError
3
+
4
+ attr_reader :code
5
+ attr_reader :headers
6
+ attr_reader :body
7
+
8
+ def initialize(env)
9
+ @code = env.status
10
+ @headers = env.response_headers
11
+ @body = env.body
12
+ end
13
+
3
14
  class << self
4
15
  # @note I ripped off RedditKit.rb :|
5
16
  def from_response(response) # rubocop:disable Style/CyclomaticComplexity Style/MethodLength
@@ -80,7 +91,11 @@ module Redd
80
91
 
81
92
  class RateLimited < Error
82
93
  attr_reader :time
83
- def initialize(time = 0)
94
+
95
+ def initialize(env, time)
96
+ @code = env.status
97
+ @headers = env.response_headers
98
+ @body = env.body
84
99
  @time = time
85
100
  end
86
101
  end
@@ -53,7 +53,7 @@ module Redd
53
53
  end
54
54
 
55
55
  def comments
56
- @comments ||= client.get_comments(id)
56
+ @comments ||= client.submission_comments(id)
57
57
  end
58
58
 
59
59
  def created
@@ -0,0 +1,116 @@
1
+ require "faraday"
2
+ require "redd/version"
3
+ require "redd/rate_limit"
4
+ require "redd/response/parse_json"
5
+ require "redd/response/raise_error"
6
+
7
+ module Redd
8
+ module Client
9
+ # The Client used to connect without needing login credentials.
10
+ class Unauthenticated
11
+ require "redd/client/unauthenticated/account"
12
+ require "redd/client/unauthenticated/captcha"
13
+ require "redd/client/unauthenticated/links_comments"
14
+ require "redd/client/unauthenticated/listing"
15
+ require "redd/client/unauthenticated/live"
16
+ require "redd/client/unauthenticated/moderation"
17
+ require "redd/client/unauthenticated/subreddits"
18
+ require "redd/client/unauthenticated/utilities"
19
+ require "redd/client/unauthenticated/wiki"
20
+
21
+ include Redd::Client::Unauthenticated::Account
22
+ include Redd::Client::Unauthenticated::Captcha
23
+ include Redd::Client::Unauthenticated::LinksComments
24
+ include Redd::Client::Unauthenticated::Listing
25
+ include Redd::Client::Unauthenticated::Live
26
+ include Redd::Client::Unauthenticated::Moderation
27
+ include Redd::Client::Unauthenticated::Subreddits
28
+ include Redd::Client::Unauthenticated::Utilities
29
+ include Redd::Client::Unauthenticated::Wiki
30
+
31
+ # @!attribute [r] api_endpoint
32
+ # @return [String] The site to connect to.
33
+ attr_accessor :api_endpoint
34
+
35
+ # @!attribute [r] user_agent
36
+ # @return [String] The user-agent used to communicate with reddit.
37
+ attr_accessor :user_agent
38
+
39
+ # @!attribute [r] rate_limit
40
+ # @return [#after_limit] The handler that takes care of rate limiting.
41
+ attr_accessor :rate_limit
42
+
43
+ # Set up an unauthenticated connection to reddit.
44
+ #
45
+ # @param [Hash] options A hash of options to connect using.
46
+ # @option options [#after_limit] :rate_limit The handler that takes care
47
+ # of rate limiting.
48
+ # @option options [String] :user_agent The User-Agent string to use in the
49
+ # header of every request.
50
+ # @option options [String] :api_endpoint The main domain to connect
51
+ # to, in this case, the URL for reddit.
52
+ def initialize(options = {})
53
+ @rate_limit = options[:rate_limit] || Redd::RateLimit.new
54
+ @user_agent = options[:user_agent] || "Redd/Ruby, v#{Redd::VERSION}"
55
+ @api_endpoint = options[:api_endpoint] || "http://www.reddit.com/"
56
+ end
57
+
58
+ private
59
+
60
+ # @return [Hash] The headers that are sent with every request.
61
+ def headers
62
+ @headers ||= {"User-Agent" => @user_agent}
63
+ end
64
+
65
+ # Gets the Faraday connection or creates one if it doesn't exist yet.
66
+ #
67
+ # @return [Faraday] A new Faraday connection.
68
+ def connection
69
+ @connection ||= Faraday.new(url: api_endpoint) do |faraday|
70
+ faraday.use Faraday::Request::UrlEncoded
71
+ faraday.use Redd::Response::RaiseError
72
+ faraday.use Redd::Response::ParseJson
73
+ faraday.adapter Faraday.default_adapter
74
+
75
+ faraday.headers = headers
76
+ end
77
+ end
78
+
79
+ # Send a request to the given path.
80
+ #
81
+ # @param [#to_sym] method The HTTP verb to use.
82
+ # @param [String] path The path under the api endpoint to request from.
83
+ # @param [Hash] params The additional parameters to send (defualt: {}).
84
+ # @return [String] The response body.
85
+ def request(method, path, params = {})
86
+ rate_limit.after_limit do
87
+ connection.send(method.to_sym, path, params).body
88
+ end
89
+ end
90
+
91
+ # Performs a GET request via {#request}.
92
+ # @see #request
93
+ def get(*args)
94
+ request(:get, *args)
95
+ end
96
+
97
+ # Performs a POST request via {#request}.
98
+ # @see #request
99
+ def post(*args)
100
+ request(:post, *args)
101
+ end
102
+
103
+ # Performs a PUT request via {#request}.
104
+ # @see #request
105
+ def put(*args)
106
+ request(:put, *args)
107
+ end
108
+
109
+ # Performs a DELETE request via {#request}.
110
+ # @see #request
111
+ def delete(*args)
112
+ request(:delete, *args)
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,27 @@
1
+ require "redd/base"
2
+
3
+ module Redd
4
+ module Object
5
+ # A submission made in a subreddit.
6
+ class WikiPage < Redd::Base
7
+ attr_reader :kind
8
+ attr_reader :may_revise
9
+ attr_reader :content_md
10
+ attr_reader :content_html
11
+
12
+ alias_method :content, :content_md
13
+ alias_method :body, :content_md
14
+
15
+ # HACK
16
+ def revision_by
17
+ @revision_by ||= client.send(
18
+ :object_from_body, @attributes[:revision_by]
19
+ )
20
+ end
21
+
22
+ def revision_date
23
+ @created ||= Time.at(@attributes[:revision_date])
24
+ end
25
+ end
26
+ end
27
+ end
@@ -8,13 +8,12 @@ module Redd
8
8
  # @param faraday
9
9
  def call(faraday)
10
10
  @app.call(faraday).on_complete do |env|
11
- error = Redd::Error.from_response(env)
12
- if error
11
+ if error = Redd::Error.from_response(env)
13
12
  if error == Redd::Error::RateLimited
14
- seconds = env[:body][:json][:ratelimit]
15
- fail error.new(seconds), env
13
+ time = env.body[:json][:ratelimit]
14
+ fail error.new(env, time)
16
15
  else
17
- fail error, env
16
+ fail error.new(env)
18
17
  end
19
18
  end
20
19
  end
data/lib/redd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # The main Redd module.
2
2
  module Redd
3
3
  # The semantic version number for Redd.
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.6"
5
5
  end
@@ -0,0 +1,15 @@
1
+ describe Redd::Client::Unauthenticated, :vcr do
2
+ let(:client) { Redd::Client::Unauthenticated.new }
3
+
4
+ it "has configurable options" do
5
+ newclient = Redd::Client::Unauthenticated.new(
6
+ rate_limit: "SPEC_RATELIMIT",
7
+ user_agent: "SPEC_USERAGENT",
8
+ api_endpoint: "SPEC_ENDPOINT.COM"
9
+ )
10
+
11
+ expect(newclient.rate_limit).to eq("SPEC_RATELIMIT")
12
+ expect(newclient.user_agent).to eq("SPEC_USERAGENT")
13
+ expect(newclient.api_endpoint).to eq("SPEC_ENDPOINT.COM")
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ describe Redd::RateLimit do
2
+ let(:rate_limit) { Redd::RateLimit.new }
3
+
4
+ it "waits two seconds between consecutive requests" do
5
+ rate_limit.after_limit { }
6
+ start_time = Time.now
7
+ rate_limit.after_limit { }
8
+ end_time = Time.now
9
+
10
+ expect(end_time - start_time).to be_within(0.1).of(2)
11
+ end
12
+
13
+ it "doesn't wait if two seconds have passed since last request" do
14
+ rate_limit.after_limit { }
15
+ sleep(2)
16
+ start_time = Time.now
17
+ rate_limit.after_limit { }
18
+ end_time = Time.now
19
+
20
+ expect(end_time - start_time).to be_within(0.1).of(0)
21
+ end
22
+
23
+ it "stores the time the last request was made" do
24
+ time = Time.now
25
+ rate_limit.after_limit { }
26
+
27
+ expect(rate_limit.last_request_time).to be_within(0.1).of(time)
28
+ end
29
+ end
data/spec/redd_spec.rb CHANGED
@@ -1,5 +1,3 @@
1
- require_relative "spec_helper"
2
-
3
1
  describe Redd do
4
2
  it "has a semantic version number" do
5
3
  expect(Redd::VERSION).to match(/\d\.\d\.\d/)
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ require "redd"
6
6
 
7
7
  VCR.configure do |config|
8
8
  config.cassette_library_dir = "spec/cassettes"
9
+ config.default_cassette_options = {record: :new_episodes}
9
10
  config.hook_into :webmock
10
11
  end
11
12
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avinash Dwarapu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-07 00:00:00.000000000 Z
11
+ date: 2014-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -201,13 +201,17 @@ files:
201
201
  - lib/redd/object/private_message.rb
202
202
  - lib/redd/object/submission.rb
203
203
  - lib/redd/object/subreddit.rb
204
+ - lib/redd/object/unauthenticated.rb
204
205
  - lib/redd/object/user.rb
206
+ - lib/redd/object/wiki_page.rb
205
207
  - lib/redd/rate_limit.rb
206
208
  - lib/redd/response/parse_json.rb
207
209
  - lib/redd/response/raise_error.rb
208
210
  - lib/redd/thing.rb
209
211
  - lib/redd/version.rb
210
212
  - redd.gemspec
213
+ - spec/redd/client/unauthenticated_spec.rb
214
+ - spec/redd/rate_limit_spec.rb
211
215
  - spec/redd_spec.rb
212
216
  - spec/spec_helper.rb
213
217
  homepage: ''
@@ -235,6 +239,8 @@ signing_key:
235
239
  specification_version: 4
236
240
  summary: A Reddit API Wrapper for Ruby.
237
241
  test_files:
242
+ - spec/redd/client/unauthenticated_spec.rb
243
+ - spec/redd/rate_limit_spec.rb
238
244
  - spec/redd_spec.rb
239
245
  - spec/spec_helper.rb
240
246
  has_rdoc: