NeonRAW 0.1.1

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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +5 -0
  5. data/.travis.yml +4 -0
  6. data/CHANGELOG.md +7 -0
  7. data/CONTRIBUTING.md +11 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.md +373 -0
  10. data/NeonRAW.gemspec +26 -0
  11. data/README.md +62 -0
  12. data/Rakefile +6 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/examples/crossposter.rb +78 -0
  16. data/examples/flairbot.rb +60 -0
  17. data/examples/publicmodlogger.rb +79 -0
  18. data/examples/settings.yaml +4 -0
  19. data/examples/userhistoryscraper.rb +108 -0
  20. data/examples/userhistorywiper.rb +10 -0
  21. data/lib/NeonRAW/clients/base/listing.rb +55 -0
  22. data/lib/NeonRAW/clients/base/objectbuilder.rb +173 -0
  23. data/lib/NeonRAW/clients/base/utilities.rb +46 -0
  24. data/lib/NeonRAW/clients/base.rb +109 -0
  25. data/lib/NeonRAW/clients/installed.rb +49 -0
  26. data/lib/NeonRAW/clients/script.rb +34 -0
  27. data/lib/NeonRAW/clients/web.rb +52 -0
  28. data/lib/NeonRAW/errors.rb +518 -0
  29. data/lib/NeonRAW/objects/access.rb +44 -0
  30. data/lib/NeonRAW/objects/all.rb +36 -0
  31. data/lib/NeonRAW/objects/comment.rb +128 -0
  32. data/lib/NeonRAW/objects/inboxcomment.rb +54 -0
  33. data/lib/NeonRAW/objects/listing.rb +12 -0
  34. data/lib/NeonRAW/objects/me.rb +268 -0
  35. data/lib/NeonRAW/objects/modlogaction.rb +59 -0
  36. data/lib/NeonRAW/objects/modloguser.rb +35 -0
  37. data/lib/NeonRAW/objects/morecomments.rb +33 -0
  38. data/lib/NeonRAW/objects/multireddit.rb +134 -0
  39. data/lib/NeonRAW/objects/privatemessage.rb +90 -0
  40. data/lib/NeonRAW/objects/rule.rb +41 -0
  41. data/lib/NeonRAW/objects/submission.rb +221 -0
  42. data/lib/NeonRAW/objects/subreddit/flair.rb +169 -0
  43. data/lib/NeonRAW/objects/subreddit/moderation.rb +200 -0
  44. data/lib/NeonRAW/objects/subreddit/utilities.rb +73 -0
  45. data/lib/NeonRAW/objects/subreddit/wiki.rb +31 -0
  46. data/lib/NeonRAW/objects/subreddit.rb +223 -0
  47. data/lib/NeonRAW/objects/thing/createable.rb +22 -0
  48. data/lib/NeonRAW/objects/thing/editable.rb +46 -0
  49. data/lib/NeonRAW/objects/thing/gildable.rb +29 -0
  50. data/lib/NeonRAW/objects/thing/inboxable.rb +26 -0
  51. data/lib/NeonRAW/objects/thing/moderateable.rb +98 -0
  52. data/lib/NeonRAW/objects/thing/refreshable.rb +21 -0
  53. data/lib/NeonRAW/objects/thing/repliable.rb +23 -0
  54. data/lib/NeonRAW/objects/thing/saveable.rb +26 -0
  55. data/lib/NeonRAW/objects/thing/votable.rb +69 -0
  56. data/lib/NeonRAW/objects/thing.rb +24 -0
  57. data/lib/NeonRAW/objects/trophy.rb +25 -0
  58. data/lib/NeonRAW/objects/user.rb +147 -0
  59. data/lib/NeonRAW/objects/wikipage.rb +176 -0
  60. data/lib/NeonRAW/objects/wikipagerevision.rb +45 -0
  61. data/lib/NeonRAW/version.rb +3 -0
  62. data/lib/NeonRAW.rb +43 -0
  63. metadata +161 -0
@@ -0,0 +1,60 @@
1
+ require 'yaml'
2
+ require 'NeonRAW'
3
+
4
+ # Creates and authenticates the client.
5
+ # @!method login(config)
6
+ # @param config [Hash] The data loaded from settings.yaml.
7
+ # @return [NeonRAW::Clients::Script] Returns the client.
8
+ def login(config)
9
+ reddit_exception_handling do
10
+ client = NeonRAW.script(config['username'], config['password'],
11
+ config['client_id'], config['secret'],
12
+ user_agent: 'Flairbot by /u/SirNeon')
13
+ return client
14
+ end
15
+ end
16
+
17
+ # Flairs submissions based on keywords in their title.
18
+ # @!method flair_shit(client, subreddit)
19
+ # @param client [NeonRAW::Clients::Script] The client.
20
+ # @param subreddit [String] The subreddit to scan.
21
+ def flair_shit(client, subreddit)
22
+ reddit_exception_handling do
23
+ subreddit = client.subreddit subreddit
24
+ submissions = subreddit.new limit: 100
25
+ submissions.each do |submission|
26
+ next if submission.flair?
27
+ case submission.title
28
+ when /\[meta\]/i then subreddit.set_flair submission, 'Meta',
29
+ css_class: 'meta'
30
+ when /test/i then subreddit.set_flair submission, 'Test'
31
+ end
32
+ end
33
+ break
34
+ end
35
+ end
36
+
37
+ # Handles Reddit exceptions.
38
+ # @!method reddit_exception_handling
39
+ # @param block [&block] The block to execute.
40
+ def reddit_exception_handling
41
+ include NeonRAW::Errors
42
+ loop do
43
+ begin
44
+ yield
45
+ rescue InvalidCredentials, InvalidOAuth2Credentials => error
46
+ abort(error.message)
47
+ rescue CouldntReachServer, ServiceUnavailable
48
+ sleep(5)
49
+ redo
50
+ end
51
+ end
52
+ end
53
+
54
+ def main
55
+ config = YAML.load_file('settings.yaml')
56
+ client = login(config)
57
+ flair_shit client, client.me.name
58
+ end
59
+
60
+ main
@@ -0,0 +1,79 @@
1
+ require 'yaml'
2
+ require 'NeonRAW'
3
+
4
+ # Creates and authenticates the client.
5
+ # @!method login(config)
6
+ # @param config [Hash] The data loaded from the settings.yaml file.
7
+ # @return [NeonRAW::Clients::Script] Returns the client.
8
+ def login(config)
9
+ reddit_exception_handling do
10
+ client = NeonRAW.script(config['username'], config['password'],
11
+ config['client_id'], config['secret'],
12
+ user_agent: 'Public mod logger by /u/SirNeon')
13
+ return client
14
+ end
15
+ end
16
+
17
+ # Fetches the modlog.
18
+ # @!method get_modlog(client, subreddit)
19
+ # @param client [NeonRAW::Clients::Script] The client.
20
+ # @param subreddit [String] The subreddit to fetch the modlog from.
21
+ # @return [NeonRAW::Objects::Listing] Returns the modlog actions.
22
+ def get_modlog(client, subreddit)
23
+ reddit_exception_handling do
24
+ subreddit = client.subreddit subreddit
25
+ modlog = subreddit.modlog limit: 100
26
+ return modlog.reverse
27
+ end
28
+ end
29
+
30
+ # Submits the modlog data to Reddit.
31
+ # @!method submit_actions(client, subreddit, modlog)
32
+ # @param client [NeonRAW::Clients::Script] The client.
33
+ # @param subreddit [String] The subreddit to submit the data to.
34
+ # @param modlog [NeonRAW::Objects::Listing] The modlog actions.
35
+ def submit_actions(client, subreddit, modlog)
36
+ reddit_exception_handling do
37
+ subreddit = client.subreddit subreddit
38
+ modlog.each do |entry|
39
+ title = entry.id
40
+ text = "Mod: #{entry.mod}\n\n"
41
+ text += "Action: #{entry.action}\n\n"
42
+ text += "Description: #{entry.description}\n\n" if entry.description
43
+ text += "Created: #{entry.created}\n\n"
44
+ text += "Target Author: #{entry.target_author}\n\n" if entry.target_author
45
+ if entry.target_permalink
46
+ text += "Target Permalink: #{entry.target_permalink}\n\n"
47
+ end
48
+ submission = subreddit.submit title, text: text
49
+ subreddit.set_flair submission, entry.action
50
+ end
51
+ break
52
+ end
53
+ end
54
+
55
+ # Handles Reddit exceptions.
56
+ # @!method reddit_exception_handling
57
+ # @param block [&block] The block to be executed.
58
+ def reddit_exception_handling
59
+ include NeonRAW::Errors
60
+ loop do
61
+ begin
62
+ yield
63
+ rescue InvalidCredentials, InvalidOAuth2Credentials => error
64
+ abort(error.message)
65
+ rescue CouldntReachServers, ServiceUnavailable
66
+ sleep(5)
67
+ redo
68
+ end
69
+ end
70
+ end
71
+
72
+ def main
73
+ config = YAML.load_file('settings.yaml')
74
+ client = login(config)
75
+ modlog = get_modlog(client, 'NeonRAW')
76
+ submit_actions(client, 'NeonRAW', modlog)
77
+ end
78
+
79
+ main
@@ -0,0 +1,4 @@
1
+ username: username
2
+ password: password
3
+ client_id: client_id
4
+ secret: secret
@@ -0,0 +1,108 @@
1
+ require 'yaml'
2
+ require 'NeonRAW'
3
+
4
+ # Creates and authenticates the client.
5
+ # @!method login(config)
6
+ # @param config [Hash] The data loaded from the settings.yaml file.
7
+ # @return [NeonRAW::Clients::Script] Returns the client.
8
+ def login(config)
9
+ reddit_exception_handling do
10
+ client = NeonRAW.script(config['username'], config['password'],
11
+ config['client_id'], config['secret'],
12
+ user_agent: 'User history scraper by /u/SirNeon')
13
+ return client
14
+ end
15
+ end
16
+
17
+ # Fetches the posts of the user.
18
+ # @!method get_posts(client, user, quantity)
19
+ # @param client [NeonRAW::Clients::Script] The client.
20
+ # @param user [String] The username of the user.
21
+ # @param quantity [1..1000] The number of posts to fetch.
22
+ # @return [NeonRAW::Objects::Listing] Returns the posts.
23
+ def get_posts(client, user, quantity)
24
+ reddit_exception_handling do
25
+ posts = client.user(user).overview limit: quantity
26
+ return posts
27
+ end
28
+ end
29
+
30
+ # Tallies the number of posts/karma per subreddit.
31
+ # @!method tally_data(posts)
32
+ # @param posts [NeonRAW::Objects::Listing] The posts.
33
+ # @return [Hash<Integer, Integer>] Returns the tallied data.
34
+ def tally_data(posts)
35
+ stats = {}
36
+ posts.each do |post|
37
+ subreddit = post.subreddit
38
+ stats[subreddit] = { posts: 0, karma: 0 } if stats[subreddit].nil?
39
+ stats[subreddit][:posts] += 1
40
+ stats[subreddit][:karma] += post.score
41
+ end
42
+ stats
43
+ end
44
+
45
+ # Sorts the data.
46
+ # @!method sort_data(data, by)
47
+ # @param data [Hash] The data.
48
+ # @param by [Symbol] The thing to sort by [posts, karma].
49
+ # @return [Hash<Integer, Integer>] Returns the sorted data.
50
+ def sort_data(data, by)
51
+ # Sort the data highest amount of posts/karma to least amount.
52
+ data.sort_by { |_subreddit, tallies| tallies[by] }.reverse.to_h
53
+ end
54
+
55
+ # Builds a table from the sorted data.
56
+ # @!method build_table(data)
57
+ # @param data [Hash] The data.
58
+ # @return [String] Returns the table.
59
+ def build_table(data)
60
+ text = "|subreddit|posts|karma|\n|:---|:---:|:---:|\n"
61
+ data.each do |subreddit, tallies|
62
+ text += "|#{subreddit}|#{tallies[:posts]}|#{tallies[:karma]}|\n"
63
+ end
64
+ text
65
+ end
66
+
67
+ # Submits the results to Reddit.
68
+ # @!method submit_results(client, subreddit, title, text)
69
+ # @param client [NeonRAW::Objects::Script] The client.
70
+ # @param subreddit [String] The name of the subreddit to submit to.
71
+ # @param title [String] The title of the thread.
72
+ # @param text [String] The table to be submitted.
73
+ def submit_results(client, subreddit, title, text)
74
+ reddit_exception_handling do
75
+ client.subreddit(subreddit).submit title, text: text
76
+ break
77
+ end
78
+ end
79
+
80
+ # Handles Reddit exceptions.
81
+ # @!method reddit_exception_handling
82
+ # @param block [&block] The block to be executed.
83
+ def reddit_exception_handling
84
+ include NeonRAW::Errors
85
+ loop do
86
+ begin
87
+ yield
88
+ rescue InvalidCredentials, InvalidOAuth2Credentials => error
89
+ abort(error.message)
90
+ rescue CouldntReachServer, ServiceUnavailable
91
+ sleep(5)
92
+ redo
93
+ end
94
+ end
95
+ end
96
+
97
+ def main
98
+ config = YAML.load_file('settings.yaml')
99
+ client = login(config)
100
+ user = client.me.name
101
+ posts = get_posts(client, user, 1000)
102
+ data = tally_data(posts)
103
+ sorted_data = sort_data(data, :posts)
104
+ text = build_table(sorted_data)
105
+ submit_results(client, user, "#{user}'s user history", text)
106
+ end
107
+
108
+ main
@@ -0,0 +1,10 @@
1
+ require 'yaml'
2
+ require 'NeonRAW'
3
+
4
+ config = YAML.load_file('settings.yaml')
5
+ client = NeonRAW.script(config['username'], config['password'],
6
+ config['client_id'], config['secret'],
7
+ user_agent: 'User history wiper by /u/SirNeon')
8
+
9
+ # Wiping your user history has never been so easy!
10
+ client.me.purge 'overview', months: 1
@@ -0,0 +1,55 @@
1
+ require_relative '../../objects/listing'
2
+ require_relative '../../objects/subreddit'
3
+ require_relative '../../objects/comment'
4
+ require_relative '../../objects/access'
5
+ require_relative '../../objects/privatemessage'
6
+ require_relative '../../objects/modlogaction'
7
+ require_relative '../../objects/inboxcomment'
8
+ require_relative '../../errors'
9
+ # rubocop:disable Metrics/AbcSize
10
+
11
+ module NeonRAW
12
+ module Clients
13
+ class Base
14
+ # Methods for building listings.
15
+ module Listings
16
+ OBJECT_KINDS = {
17
+ 'Listing' => Objects::Listing,
18
+ 'modaction' => Objects::ModLogAction,
19
+ 't1' => Objects::Comment,
20
+ 't3' => Objects::Submission,
21
+ 't4' => Objects::PrivateMessage,
22
+ 't5' => Objects::Subreddit
23
+ }.freeze
24
+
25
+ # Creates the listing object.
26
+ # @!method build_listing(path, params)
27
+ # @param path [String] The API path for the listing.
28
+ # @param params [Hash] The parameters for the request.
29
+ # @return [NeonRAW::Objects::Listing] Returns the Listing object.
30
+ def build_listing(path, params)
31
+ data_arr = []
32
+ until data_arr.length == params[:limit]
33
+ data = request_data(path, :get, params)
34
+ params[:after] = data[:data][:after]
35
+ params[:before] = data[:data][:before]
36
+ data[:data][:children].each do |item|
37
+ data_arr << if item[:kind] == 't1' &&
38
+ item[:data].key?(:was_comment)
39
+ Objects::InboxComment.new(self, item[:data])
40
+ else
41
+ OBJECT_KINDS[item[:kind]].new(self, item[:data])
42
+ end
43
+ break if data_arr.length == params[:limit]
44
+ end
45
+ break if params[:after].nil?
46
+ end
47
+ listing = OBJECT_KINDS['Listing'].new(params[:after], params[:before])
48
+ data_arr.each { |submission| listing << submission }
49
+ listing
50
+ end
51
+ private :build_listing
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,173 @@
1
+ require_relative '../../objects/subreddit'
2
+ require_relative '../../objects/user'
3
+ require_relative '../../objects/me'
4
+ require_relative '../../objects/multireddit'
5
+ require_relative '../../objects/wikipage'
6
+ require_relative '../../objects/all'
7
+
8
+ module NeonRAW
9
+ module Clients
10
+ class Base
11
+ # Methods for building objects.
12
+ module ObjectBuilder
13
+ SUBREDDIT_DEFAULTS = {
14
+ 'allow_top' => true,
15
+ 'collapse_deleted_comments' => false,
16
+ 'comment_score_hide_mins' => 0,
17
+ 'exclude_banned_modqueue' => false,
18
+ 'header-title' => '',
19
+ 'hide_ads' => false,
20
+ 'lang' => 'en',
21
+ 'link_type' => 'any',
22
+ 'over_18' => false,
23
+ 'public_traffic' => false,
24
+ 'show_media' => true,
25
+ 'spam_comments' => 'low',
26
+ 'spam_links' => 'high',
27
+ 'spam_selfposts' => 'high',
28
+ 'submit_text_label' => 'Submit a new text post',
29
+ 'submit_text' => '',
30
+ 'submit_link_label' => 'Submit a new link',
31
+ 'suggested_comment_sort' => 'confidence',
32
+ 'type' => 'public',
33
+ 'wiki_edit_age' => 0,
34
+ 'wiki_edit_karma' => 100,
35
+ 'wikimode' => 'disabled'
36
+ }.freeze
37
+
38
+ # Fetches a subreddit.
39
+ # @!method subreddit(name)
40
+ # @param name [String] The name of the subreddit.
41
+ # @return [NeonRAW::Objects::Subreddit/All] Returns the subreddit/all
42
+ # object.
43
+ def subreddit(name)
44
+ if name == 'all'
45
+ Objects::All.new(self)
46
+ else
47
+ data = request_data("/r/#{name}/about.json", :get)[:data]
48
+ Objects::Subreddit.new(self, data)
49
+ end
50
+ end
51
+
52
+ # Fetches a user.
53
+ # @!method user(name)
54
+ # @param name [String] The name of the user.
55
+ # @return [NeonRAW::Objects::User] Returns the user object.
56
+ def user(name)
57
+ data = request_data("/user/#{name}/about.json", :get)[:data]
58
+ Objects::User.new(self, data)
59
+ end
60
+
61
+ # Fetches yourself.
62
+ # @!method me
63
+ # @return [NeonRAW::Objects::Me] Returns the me object.
64
+ def me
65
+ data = request_data('/api/v1/me', :get)
66
+ Objects::Me.new(self, data)
67
+ end
68
+
69
+ # Fetches a multireddit.
70
+ # @!method multireddit(multireddit_path)
71
+ # @param multireddit_path [String] The path to the multireddit (e.g.
72
+ # /user/username/m/multireddit_name).
73
+ # @return [NeonRAW::Objects::MultiReddit] Returns the multireddit
74
+ # object.
75
+ def multireddit(multireddit_path)
76
+ params = { multipath: multireddit_path, expand_srs: false }
77
+ data = request_data("/api/multi/#{multireddit_path}", :get, params)
78
+ Objects::MultiReddit.new(self, data[:data])
79
+ end
80
+
81
+ # Creates a multireddit.
82
+ # @!method create_multireddit(data, multireddit_path)
83
+ # @param data [JSON] The multireddit data.
84
+ # @param multireddit_path [String] The path to the multireddit (e.g.
85
+ # /user/username/m/multireddit_name)
86
+ # @return [NeonRAW::Objects::MultiReddit] Returns the multireddit
87
+ # object.
88
+ # @see https://www.reddit.com/dev/api#POST_api_multi_{multipath}
89
+ def create_multireddit(data, multireddit_path)
90
+ params = { model: data, multipath: multireddit_path,
91
+ expand_srs: false }
92
+ data = request_data("/api/multi/#{multireddit_path}", :post, params)
93
+ Objects::MultiReddit.new(self, data[:data])
94
+ end
95
+
96
+ # Creates a subreddit.
97
+ # @!method create_subreddit(name, title, description, opts = {})
98
+ # @param name [String] The name of the subreddit.
99
+ # @param title [String] The title of the subreddit (100
100
+ # characters maximum).
101
+ # @param description [String] The sidebar text for the subreddit.
102
+ # @param opts [Hash] Optional parameters.
103
+ # @option opts allow_top [Boolean] Whether or not the subreddit can be
104
+ # displayed on /r/all.
105
+ # @option opts collapse_deleted_comments [Boolean] Whether or not to
106
+ # collapse deleted comments.
107
+ # @option opts comment_score_hide_mins [0..1440] The number of minutes
108
+ # to hide comment scores.
109
+ # @option opts exclude_banned_modqueue [Boolean] Whether or not to
110
+ # exclude sitewide banned users from modqueue.
111
+ # @option opts header-title [String] The title for the subreddit (500
112
+ # characters maximum).
113
+ # @option opts hide_ads [Boolean] Whether or not to hide ads in the
114
+ # subreddit.
115
+ # @option opts lang [String] The IETF language tags of the subreddit
116
+ # separated by underscores.
117
+ # @option opts link_type [String] The type of submissions allowed [any,
118
+ # link, self].
119
+ # @option opts over_18 [Boolean] Whether or not the subreddit is NSFW.
120
+ # @option opts public_description [String] The message that will get
121
+ # shown to people when the subreddit is private.
122
+ # @option opts public_traffic [Boolean] Whether or not the subreddit's
123
+ # traffic stats are publicly available.
124
+ # @option opts show_media [Boolean] Whether or not to show media.
125
+ # @option opts spam_comments [String] Set the spamfilter [low, high,
126
+ # all].
127
+ # @option opts spam_links [String] Set the spamfilter [low, high, all].
128
+ # @option opts spam_selfposts [String] Set the spamfilter [low, high,
129
+ # all].
130
+ # @option opts submit_text_label [String] The label for the selfpost
131
+ # button (60 characters maximum).
132
+ # @option opts submit_text [String] The text to display when making a
133
+ # selfpost.
134
+ # @option opts submit_link_label [String] The label for the link button
135
+ # (60 characters maximum).
136
+ # @option opts suggested_comment_sort [String] The suggested comment
137
+ # sort for the subreddit [confidence, top, new, controversial, old,
138
+ # random, qa].
139
+ # @option opts type [String] The subreddit type [gold_restricted,
140
+ # archived, restricted, gold_only, employees_only, private, public].
141
+ # @option opts wiki_edit_age [Integer] The minimum account age needed to
142
+ # edit the wiki.
143
+ # @option opts wiki_edit_karma [Integer] The minimum karma needed to
144
+ # edit the wiki.
145
+ # @option opts wikimode [String] The mode of the subreddit's wiki
146
+ # [disabled, modonly, anyone].
147
+ # @return [NeonRAW::Objects::Subreddit] Returns the subreddit object.
148
+ def create_subreddit(name, title, description, opts = {})
149
+ params = SUBREDDIT_DEFAULTS.dup
150
+ params.merge! opts
151
+ params['api_type'] = 'json'
152
+ params['name'] = name
153
+ params['title'] = title
154
+ params['description'] = description
155
+ request_data('/api/site_admin', :post, params)
156
+ subreddit(name)
157
+ end
158
+
159
+ # Fetches a wiki page.
160
+ # @!method wikipage(page)
161
+ # @param page [String] The name of the page.
162
+ # @return [NeonRAW::Objects::WikiPage] Returns the wiki page object.
163
+ def wikipage(page)
164
+ params = { page: page }
165
+ path = "/wiki/#{page}.json"
166
+ data = request_data(path, :get, params)
167
+ data[:data][:name] = page
168
+ Objects::WikiPage.new(self, data[:data])
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,46 @@
1
+ module NeonRAW
2
+ module Clients
3
+ class Base
4
+ # Utilities for the base client.
5
+ module Utilities
6
+ # Search for subreddits.
7
+ # @!method find_subreddits(query)
8
+ # @param query [String] The name to search for (50 characters maximum).
9
+ # @return [Array<String>] Returns the list of subreddits.
10
+ def find_subreddits(query)
11
+ params = { query: query }
12
+ data = request_data('/api/subreddits_by_topic', :get, params)
13
+ data.map { |subreddit| subreddit[:name] }
14
+ end
15
+
16
+ # Fetches subreddits.
17
+ # @!method popular(params = { limit: 25 })
18
+ # @!method new(params = { limit: 25 })
19
+ # @!method gold(params = { limit: 25 })
20
+ # @!method defaults(params = { limit: 25 })
21
+ # @param params [Hash] The parameters.
22
+ # @option params :after [String] Fullname of the next data block.
23
+ # @option params :before [String] Fullname of the previous data block.
24
+ # @option params :count [Integer] The number of items already in the
25
+ # listing.
26
+ # @option params :limit [1..1000] The number of listing items to fetch.
27
+ # @option params :show [String] Literally the string 'all'.
28
+ # @return [NeonRAW::Objects::Listing] Returns a listing of all the
29
+ # subreddits.
30
+ %w(popular new gold defaults).each do |type|
31
+ define_method :"#{type}" do |params = { limit: 25 }|
32
+ type.chop! if type == 'defaults'
33
+ build_listing("/subreddits/#{type}", params)
34
+ end
35
+ end
36
+
37
+ # Fetches a list of wiki pages from Reddit.
38
+ # @!method wikipages
39
+ # @return [Array<String>] Returns a list of wiki pages.
40
+ def wikipages
41
+ request_data('/wiki/pages.json', :get)[:data]
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,109 @@
1
+ require 'typhoeus'
2
+ require 'json'
3
+ require_relative 'base/listing'
4
+ require_relative 'base/objectbuilder'
5
+ require_relative 'base/utilities'
6
+ require_relative '../errors'
7
+
8
+ module NeonRAW
9
+ module Clients
10
+ # The underlying base for the client
11
+ class Base
12
+ include Base::Listings
13
+ include Base::ObjectBuilder
14
+ include Base::Utilities
15
+ include Errors
16
+
17
+ # Creates headers for oAuth2 requests.
18
+ # @!method api_headers
19
+ # @return [Hash] Returns oAuth2 headers.
20
+ def api_headers
21
+ {
22
+ 'User-Agent' => @user_agent,
23
+ 'Authorization' => "bearer #{@access.access_token}"
24
+ }
25
+ end
26
+
27
+ # Connects to Reddit for oAuth2 requests.
28
+ # @!method api_connection(path, meth, params)
29
+ # @param path [String] The API path.
30
+ # @param meth [Symbol] The request method.
31
+ # @param params [Hash] The parameters.
32
+ # @param opts [Hash] Optional parameters for the request body.
33
+ # @return [Typhoeus::Response] Returns the response.
34
+ def api_connection(path, meth, params, opts = {})
35
+ response = Typhoeus::Request.new(
36
+ 'https://oauth.reddit.com' + path,
37
+ method: meth,
38
+ body: opts,
39
+ headers: api_headers,
40
+ params: params
41
+ ).run
42
+ error = assign_errors(response)
43
+ fail error unless error.nil?
44
+ handle_ratelimit(response.headers)
45
+ response
46
+ end
47
+
48
+ # Makes the connection used to authorize the client.
49
+ # @!method auth_connection(path, meth, params)
50
+ # @param path [String] The API path.
51
+ # @param meth [Symbol] The request method.
52
+ # @param params [Hash] The parameters.
53
+ # @return [Typhoeus::Response] Returns the response.
54
+ def auth_connection(path, meth, params)
55
+ response = Typhoeus::Request.new(
56
+ 'https://www.reddit.com' + path,
57
+ method: meth,
58
+ userpwd: "#{@client_id}:#{@secret}",
59
+ headers: { 'User-Agent' => @user_agent },
60
+ params: params
61
+ ).run
62
+ error = assign_errors(response)
63
+ fail error unless error.nil?
64
+ response
65
+ end
66
+
67
+ # Refreshes the access token.
68
+ # @!method refresh_access!
69
+ def refresh_access!
70
+ response = auth_connection(
71
+ '/api/v1/access_token', :post,
72
+ grant_type: 'refresh_token',
73
+ refresh_token: @access.refresh_token
74
+ )
75
+ data = JSON.parse(response.body, symbolize_names: true)
76
+ @access.refresh! data
77
+ end
78
+
79
+ # Requests data from Reddit.
80
+ # @!method request_data(path, meth, params = {})
81
+ # @param path [String] The API path to connect to.
82
+ # @param meth [Symbol] The request method to use.
83
+ # @param params [Hash] Parameters for the request.
84
+ # @param opts [Hash] Optional parameters for methods that send stuff
85
+ # via the request body.
86
+ # @return [Hash] Returns the parsed JSON containing the response data.
87
+ def request_data(path, meth, params = {}, opts = {})
88
+ refresh_access! if @access.expired?
89
+ response = api_connection(path, meth, params, opts)
90
+ data = JSON.parse(response.body, symbolize_names: true)
91
+ error = parse_errors(data)
92
+ fail error unless error.nil?
93
+ data
94
+ end
95
+
96
+ # Requests non-JSON data from Reddit.
97
+ # @!method request_nonjson(path, meth, params = {}, opts = {})
98
+ # @param path [String] The API path to connect to.
99
+ # @param meth [Symbol] The request method to use.
100
+ # @param params [Hash] Parameters for the request.
101
+ # @param opts [Hash] Optional parameters for methods that send stuff
102
+ # via the request body.
103
+ def request_nonjson(path, meth, params = {}, opts = {})
104
+ refresh_access! if @access.expired?
105
+ api_connection(path, meth, params, opts).body
106
+ end
107
+ end
108
+ end
109
+ end