reddit_api 0.1.18 → 0.2.0
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 +4 -4
- data/lib/reddit_api/client.rb +27 -85
- data/lib/reddit_api/comments.rb +18 -8
- data/lib/reddit_api/posts.rb +11 -2
- data/lib/reddit_api/query.rb +56 -0
- data/lib/reddit_api/requestor.rb +16 -28
- data/lib/reddit_api/response_parser.rb +48 -0
- data/lib/reddit_api/subreddits.rb +23 -7
- data/lib/reddit_api/version.rb +1 -1
- data/lib/reddit_api.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2c1a49844a77703602af21827434a0d54f4db28
|
4
|
+
data.tar.gz: d59933c5bbeb7b06c38bf1319c99ed6e343317e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a631d30ae80980cab7ba975181c0e015da0abe7a98004f317f435fc99c92630c9cb93cddb063899f291cc4cd18b78cf032e64826c3f19a5506b9b012a1738d1
|
7
|
+
data.tar.gz: 7ff3eda53055f62798f0344de7debca41da2e541806248d007ae0e9450f8a2ce0434c8872b5956909215ae0f186b132dc2c40c7634b193dab9982578ebc6c59e
|
data/lib/reddit_api/client.rb
CHANGED
@@ -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
|
-
@
|
22
|
+
@parser = args.fetch(:parser, RedditApi::ResponseParser)
|
24
23
|
@null_response_factory = RedditApi:: NullResponse
|
25
|
-
@
|
24
|
+
@failures = args.fetch(:failures, 0)
|
26
25
|
end
|
27
26
|
|
28
|
-
def get(
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
37
|
+
attr_writer :failures
|
38
38
|
private
|
39
|
-
attr_reader :client, :
|
40
|
-
:requestor
|
39
|
+
attr_reader :client, :null_response_factory, :requestor, :parser
|
41
40
|
|
42
|
-
def
|
41
|
+
def send_request(query)
|
43
42
|
sleep(SLEEP_TIME)
|
44
|
-
|
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
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
90
|
-
|
55
|
+
def update_query(query, response)
|
56
|
+
query.add_records(response)
|
91
57
|
end
|
92
58
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
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
|
103
|
-
|
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
|
data/lib/reddit_api/comments.rb
CHANGED
@@ -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
|
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)
|
data/lib/reddit_api/posts.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/reddit_api/requestor.rb
CHANGED
@@ -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(
|
18
|
-
url = base_url + endpoint
|
15
|
+
def build(query)
|
16
|
+
url = base_url + query.endpoint
|
19
17
|
headers = generate_headers
|
20
|
-
|
21
|
-
[url, { headers: headers, 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
|
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(
|
32
|
+
def generate_query(query)
|
36
33
|
{
|
37
|
-
limit:
|
38
|
-
after: generate_after(resource_type,
|
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,
|
43
|
-
if
|
44
|
-
build_after(resource_type,
|
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,
|
47
|
+
def build_after(resource_type, offset_id)
|
51
48
|
prefix = TYPE_PREFIXES[resource_type]
|
52
|
-
|
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
|
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
|
-
|
17
|
-
|
18
|
-
build_subreddit(
|
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
|
-
|
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
|
52
|
+
subreddit_factory.new(subreddit_data)
|
37
53
|
end
|
38
54
|
|
39
55
|
end
|
data/lib/reddit_api/version.rb
CHANGED
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.
|
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-
|
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
|