reddit_api 0.1.18 → 0.2.0

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: fff7c79ae95004afc62a96034a80d48fdb33d9c5
4
- data.tar.gz: 00e2b4d24fe666eb5bc55a885073dcaf56089c75
3
+ metadata.gz: e2c1a49844a77703602af21827434a0d54f4db28
4
+ data.tar.gz: d59933c5bbeb7b06c38bf1319c99ed6e343317e8
5
5
  SHA512:
6
- metadata.gz: 731f3fa32a0fdf3d3a832b54fdcc300e29046f1a303e68cd59192154b8aa4642689a116d9efdbfffa184b9de77d4cdb462f898887a0790ade90427f7b5670d45
7
- data.tar.gz: bc467855c109fa8eb474fdd58f6d42bef2e1127da3e66bedd0d16138f550df981bba3c0f9132735b0787562d0e47dbcb6a2c47021af2e373bb956935c9a3a7c5
6
+ metadata.gz: 6a631d30ae80980cab7ba975181c0e015da0abe7a98004f317f435fc99c92630c9cb93cddb063899f291cc4cd18b78cf032e64826c3f19a5506b9b012a1738d1
7
+ data.tar.gz: 7ff3eda53055f62798f0344de7debca41da2e541806248d007ae0e9450f8a2ce0434c8872b5956909215ae0f186b132dc2c40c7634b193dab9982578ebc6c59e
@@ -11,117 +11,59 @@ module RedditApi
11
11
  end
12
12
  end
13
13
 
14
- attr_reader :agent, :id, :password, :secret, :username, :failures
15
-
16
- MAX_FAILURES = 5
17
- ERROR_CODES = (400..511)
18
14
  SLEEP_TIME = self.sleep_time
15
+ MAX_FAILURES = 5
16
+
17
+ attr_reader :failures
19
18
 
20
19
  def initialize(args = {})
21
20
  @client = args.fetch(:client, HTTParty)
22
21
  @requestor = args.fetch(:requestor, RedditApi::Requestor.new(client: client))
23
- @failures = args.fetch(:failures, 0)
22
+ @parser = args.fetch(:parser, RedditApi::ResponseParser)
24
23
  @null_response_factory = RedditApi:: NullResponse
25
- @last_record = nil
24
+ @failures = args.fetch(:failures, 0)
26
25
  end
27
26
 
28
- def get(endpoint, count, resource_type, offset = nil)
29
- if count > 1
30
- get_many(endpoint, count, resource_type, offset)
31
- else
32
- get_one(endpoint, count, resource_type)
27
+ def get(query)
28
+ while query.capture_count < query.count && failures < MAX_FAILURES
29
+ response = send_request(query)
30
+ response = parser.parse_response(response, query.count)
31
+ update_progress(query, response)
33
32
  end
33
+ reset_failures
34
34
  end
35
35
 
36
36
  protected
37
- attr_writer :failures, :last_record
37
+ attr_writer :failures
38
38
  private
39
- attr_reader :client, :base_url, :null_response_factory, :last_record,
40
- :requestor
39
+ attr_reader :client, :null_response_factory, :requestor, :parser
41
40
 
42
- def get_many(endpoint, count, resource_type, offset)
41
+ def send_request(query)
43
42
  sleep(SLEEP_TIME)
44
- records = {}
45
- self.last_record = offset
46
- while !break_get?(records, count)
47
- new_records = request_records(endpoint, count, resource_type)
48
- collect_records(new_records, records, count)
49
- end
50
- after_collection
51
- records.keys
52
- end
53
-
54
- def get_one(endpoint, count, resource_type)
55
- request_records(endpoint, count, resource_type)
56
- end
57
-
58
- def request_records(endpoint, count, resource_type)
59
- response = send_request(endpoint, resource_type)
60
- parse_response(response, count)
61
- end
62
-
63
- def collect_records(new_records, collected_records, count)
64
- new_records.each do |record|
65
- collected_records[record] = true
66
- break if collected_records.length == count
67
- end
68
- end
69
-
70
- def after_collection
71
- self.last_record = nil
72
- self.failures = 0
73
- end
74
-
75
- def send_request(endpoint, resource_type)
76
- request = requestor.build(endpoint, resource_type, last_record)
43
+ request = requestor.build(query)
77
44
  response = client.get(*request)
78
45
  response || null_response_factory.new
79
46
  end
80
47
 
81
- def parse_response(response, count)
82
- if bad_response?(response)
83
- handle_bad_response(count)
84
- else
85
- handle_successful_response(response, count)
86
- end
48
+ def update_progress(query, response)
49
+ captured_before = query.capture_count
50
+ update_query(query, response)
51
+ captured_after = query.capture_count
52
+ update_failures(captured_before, captured_after, query.count)
87
53
  end
88
54
 
89
- def bad_response?(response)
90
- ERROR_CODES.cover?(response.code) || response["error"]
55
+ def update_query(query, response)
56
+ query.add_records(response)
91
57
  end
92
58
 
93
- def handle_bad_response(count)
94
- self.failures += 1
95
- if count > 1
96
- []
97
- else
98
- nil
59
+ def update_failures(captured_before, captured_after, count)
60
+ if captured_before >= captured_after
61
+ self.failures += 1
99
62
  end
100
63
  end
101
64
 
102
- def handle_successful_response(response, count)
103
- if count > 1
104
- handle_plural_response(response)
105
- else
106
- response
107
- end
108
- end
109
-
110
- def handle_plural_response(response)
111
- if records = response["data"]["children"]
112
- store_last_record(records)
113
- else
114
- handle_bad_response
115
- end
116
- end
117
-
118
- def store_last_record(records)
119
- self.last_record = records[-1]
120
- records
121
- end
122
-
123
- def break_get?(records, desired_count)
124
- records.length >= desired_count || failures >= MAX_FAILURES
65
+ def reset_failures
66
+ self.failures = 0
125
67
  end
126
68
 
127
69
  end
@@ -7,6 +7,7 @@ module RedditApi
7
7
  def initialize(args = {})
8
8
  @client = args.fetch(:client, RedditApi::Client.new)
9
9
  @comment_factory = RedditApi::Comment
10
+ @query_factory = RedditApi::Query
10
11
  @offset = nil
11
12
  @failures = 0
12
13
  end
@@ -26,7 +27,7 @@ module RedditApi
26
27
  subreddits.keys
27
28
  end
28
29
 
29
- def most_recent_comments(user, count = 100, offset = nil)
30
+ def most_recent_comments(user, count, offset = nil)
30
31
  comments_data = most_recent_comment_data(user.username, count, offset)
31
32
  build_all_comments(comments_data)
32
33
  end
@@ -35,7 +36,22 @@ module RedditApi
35
36
  attr_accessor :failures
36
37
  attr_writer :offset, :failures
37
38
  private
38
- attr_reader :client, :comment_factory, :offset
39
+ attr_reader :client, :comment_factory, :offset, :query_factory
40
+
41
+ def most_recent_comment_data(username, count, offset)
42
+ return [] if username == "[deleted]"
43
+ query = build_query(username, count, offset)
44
+ client.get(query)
45
+ query.captured_records
46
+ end
47
+
48
+ def build_query(username, count, offset)
49
+ endpoint = "user/#{username}/comments.json"
50
+ query_factory.new(count: count,
51
+ endpoint: endpoint,
52
+ resource: :comment,
53
+ offset: offset)
54
+ end
39
55
 
40
56
  def update_progress(comments)
41
57
  if comments.empty?
@@ -45,12 +61,6 @@ module RedditApi
45
61
  end
46
62
  end
47
63
 
48
- def most_recent_comment_data(username, count, offset)
49
- return [] if username == "[deleted]"
50
- endpoint = "user/#{username}/comments.json"
51
- client.get(endpoint, count, :comment, offset)
52
- end
53
-
54
64
  def build_all_comments(comments_data)
55
65
  comments_data.map! do |comment_data|
56
66
  build_comment(comment_data)
@@ -5,6 +5,7 @@ module RedditApi
5
5
  def initialize
6
6
  @client = RedditApi::Client.new
7
7
  @post_factory = RedditApi::Post
8
+ @query_factory = RedditApi::Query
8
9
  end
9
10
 
10
11
  def top(subreddit, count)
@@ -14,11 +15,19 @@ module RedditApi
14
15
  end
15
16
 
16
17
  private
17
- attr_reader :client, :post_factory
18
+ attr_reader :client, :post_factory, :query_factory
18
19
 
19
20
  def top_data(subreddit, count)
21
+ query = build_query(subreddit, count)
22
+ client.get(query)
23
+ query.captured_records
24
+ end
25
+
26
+ def build_query(subreddit, count)
20
27
  endpoint = URI.encode("r/#{subreddit.name}/hot.json")
21
- client.get(endpoint, count, :post)
28
+ query_factory.new(count: count,
29
+ endpoint: endpoint,
30
+ resource: :post)
22
31
  end
23
32
 
24
33
  def filter_out(posts_data, filter)
@@ -0,0 +1,56 @@
1
+
2
+ module RedditApi
3
+ class Query
4
+
5
+ attr_reader :count, :endpoint, :offset_id, :resource_type
6
+
7
+ def initialize(args = {})
8
+ @count = args.fetch(:count)
9
+ @endpoint = args.fetch(:endpoint, "")
10
+ @offset_id = args.fetch(:offset, "")
11
+ @records = args.fetch(:records, {})
12
+ @resource_type = args.fetch(:resource, "")
13
+ end
14
+
15
+ def add_records(new_records)
16
+ if count > 1
17
+ add_multiple_records(new_records)
18
+ else
19
+ add_single_record(new_records)
20
+ end
21
+ end
22
+
23
+ def captured_records
24
+ records.values
25
+ end
26
+
27
+ def capture_count
28
+ records.length
29
+ end
30
+
31
+ protected
32
+ attr_writer :offset_id
33
+ private
34
+ attr_reader :records
35
+
36
+ def add_multiple_records(new_records)
37
+ new_records.each do |record|
38
+ record_id = record["data"]["id"]
39
+ records[record_id] = record
40
+ update_offset_id(record_id)
41
+ break if records.length == count
42
+ end
43
+ end
44
+
45
+ def add_single_record(record)
46
+ record_id = record["id"]
47
+ records[record_id] = record
48
+ update_offset_id(record_id)
49
+ end
50
+
51
+ def update_offset_id(record_id)
52
+ self.offset_id = record_id
53
+ end
54
+
55
+ end
56
+ end
@@ -2,66 +2,54 @@
2
2
  module RedditApi
3
3
  class Requestor
4
4
 
5
- MAXIMUM_RECORDS = 100
6
-
7
5
  def initialize(args = {})
8
- @client = args.fetch(:client, HTTParty)
9
6
  @agent = ENV["REDDIT_AGENT"]
7
+ @base_url = "https://oauth.reddit.com/"
8
+ @client = args.fetch(:client, HTTParty)
10
9
  @id = ENV["REDDIT_ID"]
11
10
  @password = ENV["REDDIT_PASSWORD"]
12
11
  @secret = ENV["REDDIT_SECRET"]
13
12
  @username = ENV["REDDIT_USERNAME"]
14
- @base_url = "https://oauth.reddit.com/"
15
13
  end
16
14
 
17
- def build(endpoint, resource_type, last_record = nil)
18
- url = base_url + endpoint
15
+ def build(query)
16
+ url = base_url + query.endpoint
19
17
  headers = generate_headers
20
- query = generate_query(resource_type, last_record)
21
- [url, { headers: headers, query: query }]
18
+ api_query = generate_query(query)
19
+ [url, { headers: headers, query: api_query }]
22
20
  end
23
21
 
24
22
  private
25
- attr_reader :agent, :base_url, :id, :password, :secret, :username, :client
23
+ attr_reader :agent, :base_url, :client, :id, :password, :secret, :username
26
24
 
27
25
  def generate_headers
28
- access_token = generate_access_token
29
26
  {
30
27
  "Authorization" => "bearer #{access_token}",
31
28
  "user-agent" => agent
32
29
  }
33
30
  end
34
31
 
35
- def generate_query(resource_type, last_record)
32
+ def generate_query(query)
36
33
  {
37
- limit: MAXIMUM_RECORDS,
38
- after: generate_after(resource_type, last_record)
34
+ limit: query.count,
35
+ after: generate_after(query.resource_type, query.offset_id)
39
36
  }
40
37
  end
41
38
 
42
- def generate_after(resource_type, last_record)
43
- if last_record
44
- build_after(resource_type, last_record)
39
+ def generate_after(resource_type, offset_id)
40
+ if offset_id
41
+ build_after(resource_type, offset_id)
45
42
  else
46
43
  ""
47
44
  end
48
45
  end
49
46
 
50
- def build_after(resource_type, record)
47
+ def build_after(resource_type, offset_id)
51
48
  prefix = TYPE_PREFIXES[resource_type]
52
- last_resource_id = record_id(record)
53
- "#{prefix}_#{last_resource_id}"
54
- end
55
-
56
- def record_id(record)
57
- if record.is_a?(Hash)
58
- record["data"]["id"]
59
- else
60
- record
61
- end
49
+ "#{prefix}_#{offset_id}"
62
50
  end
63
51
 
64
- def generate_access_token
52
+ def access_token
65
53
  url = "https://www.reddit.com/api/v1/access_token"
66
54
  basic_auth = { username: id,
67
55
  password: secret }
@@ -0,0 +1,48 @@
1
+
2
+ module RedditApi
3
+ module ResponseParser
4
+ class << self
5
+
6
+ ERROR_CODES = (400..511)
7
+
8
+ def parse_response(response, count)
9
+ if bad_response?(response)
10
+ handle_bad_response(count)
11
+ else
12
+ handle_successful_response(response, count)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def bad_response?(response)
19
+ ERROR_CODES.cover?(response.code) || response["error"]
20
+ end
21
+
22
+ def handle_bad_response(count)
23
+ if count > 1
24
+ []
25
+ else
26
+ {}
27
+ end
28
+ end
29
+
30
+ def handle_successful_response(response, count)
31
+ if count > 1
32
+ handle_plural_response(response)
33
+ else
34
+ handle_singular_response(response)
35
+ end
36
+ end
37
+
38
+ def handle_plural_response(response)
39
+ response["data"]["children"]
40
+ end
41
+
42
+ def handle_singular_response(response)
43
+ response["data"]
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -5,6 +5,7 @@ module RedditApi
5
5
  def initialize
6
6
  @client = RedditApi::Client.new
7
7
  @subreddit_factory = RedditApi::Subreddit
8
+ @query_factory = RedditApi::Query
8
9
  end
9
10
 
10
11
  def top(count)
@@ -13,27 +14,42 @@ module RedditApi
13
14
  end
14
15
 
15
16
  def data_for(subreddit)
16
- endpoint = "r/#{subreddit.name}/about.json"
17
- response = client.get(endpoint, 1, :subreddit)
18
- build_subreddit(response)
17
+ query = build_singular_query(subreddit)
18
+ client.get(query)
19
+ build_subreddit(query.captured_records.first)
19
20
  end
20
21
 
21
22
  private
22
- attr_reader :client, :subreddit_factory
23
+ attr_reader :client, :subreddit_factory, :query_factory
23
24
 
24
25
  def top_data(count)
26
+ query = build_plural_query(count)
27
+ client.get(query)
28
+ query.captured_records
29
+ end
30
+
31
+ def build_plural_query(count)
25
32
  endpoint = "subreddits/popular.json"
26
- client.get(endpoint, count, :subreddit)
33
+ query_factory.new(count: count,
34
+ endpoint: endpoint,
35
+ resource: :subreddit)
36
+ end
37
+
38
+ def build_singular_query(subreddit)
39
+ endpoint = "r/#{subreddit.name}/about.json"
40
+ query_factory.new(count: 1,
41
+ endpoint: endpoint,
42
+ resource: :subreddit)
27
43
  end
28
44
 
29
45
  def build_all_subreddits(subreddits_data)
30
46
  subreddits_data.map! do |subreddit_data|
31
- build_subreddit(subreddit_data)
47
+ build_subreddit(subreddit_data["data"])
32
48
  end
33
49
  end
34
50
 
35
51
  def build_subreddit(subreddit_data)
36
- subreddit_factory.new(subreddit_data["data"])
52
+ subreddit_factory.new(subreddit_data)
37
53
  end
38
54
 
39
55
  end
@@ -1,3 +1,3 @@
1
1
  module RedditApi
2
- VERSION = "0.1.18"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/reddit_api.rb CHANGED
@@ -2,7 +2,9 @@ require "reddit_api/version"
2
2
  require "dotenv/load"
3
3
  require "reddit_api/null_response"
4
4
  require "reddit_api/resource_type_prefixes"
5
+ require "reddit_api/query"
5
6
  require "reddit_api/requestor"
7
+ require "reddit_api/response_parser"
6
8
  require "reddit_api/client"
7
9
  require "reddit_api/subreddits"
8
10
  require "reddit_api/subreddit"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reddit_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.18
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Fuentes
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-20 00:00:00.000000000 Z
11
+ date: 2017-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -149,8 +149,10 @@ files:
149
149
  - lib/reddit_api/null_response.rb
150
150
  - lib/reddit_api/post.rb
151
151
  - lib/reddit_api/posts.rb
152
+ - lib/reddit_api/query.rb
152
153
  - lib/reddit_api/requestor.rb
153
154
  - lib/reddit_api/resource_type_prefixes.rb
155
+ - lib/reddit_api/response_parser.rb
154
156
  - lib/reddit_api/subreddit.rb
155
157
  - lib/reddit_api/subreddits.rb
156
158
  - lib/reddit_api/user.rb