redd 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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: