snoo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ .DS_Store
@@ -0,0 +1 @@
1
+ --markup markdown
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in snoo.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jeff Sandberg
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,86 @@
1
+ # Snoo
2
+
3
+ Snoo is a *simple* wrapper for the reddit.com api. Its designed to provide an interface as close to the official api as possible, while freeing you from the problems of dealing with json, webserver requests, and session/cookie management.
4
+
5
+ Unlike other API wrappers, this one doesn't make use of complicated objects or classes, once you instantiate it once, you are good to go.
6
+
7
+ Since it's designed to be simple, it leaves things like rate limiting up to you. Please follow the [reddit api rules](https://github.com/reddit/reddit/wiki/API) and only send one request every 2 seconds (you can use `sleep 2` between requests).
8
+
9
+ Also, if you build programs with it, please change the user agent to your specific use case.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'snoo'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install snoo
24
+
25
+ ## Usage
26
+
27
+ Here's a simple script that sends a private message:
28
+
29
+ ```ruby
30
+ require 'snoo'
31
+
32
+ # Create a new instance of the client
33
+ reddit = Snoo::Client.new
34
+
35
+ # Log into reddit
36
+ reddit.log_in 'Username', 'Password'
37
+
38
+ # Send a private message to me (Paradox!)
39
+ reddit.send_pm 'Paradox', 'Snoo rubygem rocks!', "Hey Paradox, I'm trying your Snoo rubygem out and it rocks. Thanks for providing such an awesome thing!"
40
+
41
+ # Log back out of reddit
42
+ reddit.log_out
43
+ ```
44
+
45
+ See the [docs](http://rubydoc.info/github/paradox460/snoo/) for more info.
46
+
47
+ ## Contributing
48
+
49
+ 1. Fork it
50
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
51
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
52
+ 4. Test your changes (via `rspec`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
55
+
56
+ ## Testing
57
+
58
+ 1. Edit `spec/auth.rb` and fill out all the globals with a test user account and test reddit
59
+ 2. Run rspec
60
+
61
+ ## License
62
+
63
+ ```
64
+ Copyright (c) 2012 Jeff Sandberg
65
+
66
+ MIT License
67
+
68
+ Permission is hereby granted, free of charge, to any person obtaining
69
+ a copy of this software and associated documentation files (the
70
+ "Software"), to deal in the Software without restriction, including
71
+ without limitation the rights to use, copy, modify, merge, publish,
72
+ distribute, sublicense, and/or sell copies of the Software, and to
73
+ permit persons to whom the Software is furnished to do so, subject to
74
+ the following conditions:
75
+
76
+ The above copyright notice and this permission notice shall be
77
+ included in all copies or substantial portions of the Software.
78
+
79
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
80
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
81
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
82
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
83
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
84
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
85
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
86
+ ```
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ desc 'Uninstall snoo, build it, and install it locally'
5
+ task :cycle do
6
+ sh 'gem uninstall snoo'
7
+ Rake::Task["install"].execute
8
+ end
@@ -0,0 +1,38 @@
1
+ require 'httparty'
2
+
3
+ %w{version exceptions utilities account flair links_comments listings moderation pms subreddits users}.each do |local|
4
+ require "snoo/#{local}"
5
+ end
6
+ # Snoo reddit API wrapper
7
+ #
8
+ # @author Jeff Sandberg <paradox460@gmail.com>
9
+ module Snoo
10
+ # Snoo reddit API wrapper
11
+ #
12
+ # @author (see Snoo)
13
+ class Client
14
+ include HTTParty
15
+ [Account, Flair, LinksComments, Listings, Moderation, PM, Utilities, User, Subreddit].each do |inc|
16
+ include inc
17
+ end
18
+
19
+ attr_reader(:modhash, :username, :userid, :cookie)
20
+
21
+
22
+ # Creates a new instance of Snoo.
23
+ #
24
+ # Please change the useragent if you write your own program.
25
+ #
26
+ # @param url [String] url The base url of reddit.
27
+ # @param useragent [String] The User-Agent this bot will use.
28
+ def initialize( url = "http://www.reddit.com", useragent = "Snoo ruby reddit api wrapper v#{VERSION}" )
29
+ @baseurl = url
30
+ self.class.base_uri url
31
+ @headers = {'User-Agent' => useragent }
32
+ self.class.headers @headers
33
+ @cookies = nil
34
+ @modhash = nil
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,92 @@
1
+ module Snoo
2
+ # Account related methods, such as logging in, deleting the current user, changing passwords, etc
3
+ #
4
+ # @author (see Snoo)
5
+ module Account
6
+
7
+ # Log into a reddit account. You need to do this to use any restricted or write APIs
8
+ #
9
+ # @param username [String] The reddit account's username you wish to log in as
10
+ # @param password [String] The password of the reddit account
11
+ # @return [HTTParty::Response] The httparty request object.
12
+ def log_in username, password
13
+ login = post("/api/login", :body => {user: username, passwd: password, api_type: 'json'})
14
+ errors = login['json']['errors']
15
+ raise errors[0][1] unless errors.size == 0
16
+ cookies login.headers['set-cookie']
17
+ @modhash = login['json']['data']['modhash']
18
+ @username = username
19
+ @userid = 't2_' + get('/api/me.json')['data']['id']
20
+ return login
21
+ end
22
+
23
+ # Logs out of a reddit account. This is usually uneeded, you can just log_in as a new account to replace the current one.
24
+ # This just nils the cookies and modhash
25
+ def log_out
26
+ cookies nil
27
+ @modhash = nil
28
+ @userid = nil
29
+ @username = nil
30
+ end
31
+
32
+ # Invalidates all other reddit session cookies, and updates the current one.
33
+ # This will log out all other reddit clients, as described in the [reddit API](http://www.reddit.com/dev/api#POST_api_clear_sessions)
34
+ #
35
+ # @note This method provides no verification or checking, so use with care
36
+ # @param password [String] The password of the reddit account
37
+ # @return (see #log_in)
38
+ def clear_sessions password
39
+ logged_in?
40
+ clear = post('/api/clear_sessions', body: { curpass: password, dest: @baseurl, uh: @modhash })
41
+ cookies clear.headers['set-cookie']
42
+ return clear
43
+ end
44
+
45
+ # Deletes the current user. This requires a password for security reasons.
46
+ #
47
+ # @note (see #clear_sessions)
48
+ # @param password [String] The password for the current user
49
+ # @param reason [String] The reason the current user account is being deleted.
50
+ # @return (see #clear_sessions)
51
+ def delete_user password, reason = "deleted by script command"
52
+ logged_in?
53
+ delete = post('/api/delete_user', body: {
54
+ confirm: true,
55
+ delete_message: reason,
56
+ passwd: password,
57
+ uh: @modhash,
58
+ user: @username
59
+ })
60
+ return delete
61
+ end
62
+
63
+ # Gets info about the currently logged in user.
64
+ # @return (see #clear_sessions)
65
+ def me
66
+ logged_in?
67
+ get("/api/me.json")
68
+ end
69
+
70
+ # Changes the current user's password/email.
71
+ #
72
+ # @note (see #clear_sessions)
73
+ # @param currentPass [String] The current password
74
+ # @param newPass [String] The new password
75
+ # @param email [String] The email address you would like to update to. Optional
76
+ # @return (see #clear_sessions)
77
+ def update_user currentPass, newPass, email = nil
78
+ logged_in?
79
+ params = {
80
+ curpass: currentPass,
81
+ newpass: newPass,
82
+ uh: @modhash,
83
+ verify: true,
84
+ verpass: newPass
85
+ }
86
+ params[:email] = email if email
87
+ update = post('/api/update', body: params )
88
+ cookies update.headers['set-cookie']
89
+ return update
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,13 @@
1
+ module Snoo
2
+ # Not Authenticated exception. Thrown whenever a user is not logged into reddit and they should be
3
+ #
4
+ # @author (see Snoo)
5
+ class NotAuthenticated < StandardError
6
+ end
7
+
8
+ # Thrown whenever the webserver returns anyting but 200
9
+ #
10
+ # @author (see Snoo)
11
+ class WebserverError < StandardError
12
+ end
13
+ end
@@ -0,0 +1,184 @@
1
+ module Snoo
2
+ # Flair related methods.
3
+ # These are used for interacting with flair in reddit. Things like giving flair, setting templates, and whatnot.
4
+ #
5
+ # @author (see Snoo)
6
+ module Flair
7
+
8
+ # Clear all the flair templates of a particular type
9
+ #
10
+ # @param type [USER_FLAIR, LINK_FLAIR] The type of template to clear.
11
+ # @param subreddit [String] The subreddit targeted.
12
+ # @return (see #clear_sessions)
13
+ def clear_flair_templates type, subreddit
14
+ logged_in?
15
+ tests = ['USER_FLAIR', 'LINK_FLAIR']
16
+ raise ArgumentError, 'type needs to be either USER_FLAIR or LINK_FLAIR' unless tests.include?(type)
17
+ post('/api/clearflairtemplates', body: { flair_type: type, r: subreddit, uh: @modhash})
18
+ end
19
+
20
+ # Deletes a user's flair
21
+ #
22
+ # @param user [String] The user who'se flair is affected
23
+ # @param subreddit [String] The subreddit targeted.
24
+ # @return (see #clear_sessions)
25
+ def delete_user_flair user, subreddit
26
+ logged_in?
27
+ post('/api/deleteflair', body: {name: user, r: subreddit, uh: @modhash})
28
+ end
29
+
30
+ # Deletes a flair template by ID.
31
+ #
32
+ # @param id [String] The flair template's ID to delete. Get this from {#flair_template_list}
33
+ # @param subreddit [String] The subreddit targeted.
34
+ def delete_flair_template id, subreddit
35
+ logged_in?
36
+ post('/api/deleteflairtemplate', body: {flair_template_id: id, r: subreddit, uh: @modhash})
37
+ end
38
+
39
+ # Sets flair on a thing, currently supports links and users. Must specify **either** link *or* user, **not** both
40
+ #
41
+ # @param subreddit [String] The subreddit targeted.
42
+ # @param opts [Hash] An options hash.
43
+ # @option opts [String] :css_class The class(es) applied to the flair. Whitespace separated
44
+ # @option opts [String] :text The flair text
45
+ # @option opts [String] :name The user who we are flairing. This requires a username.r
46
+ # @option opts [String] :link The thing id of the link (if a link). Begins with `t3_`
47
+ # @return (see #clear_sessions)
48
+ def flair subreddit, opts = {}
49
+ logged_in?
50
+ raise ArgumentError, "link or name, not both" if opts[:link] && opts[:name]
51
+ params = {
52
+ r: subreddit,
53
+ uh: @modhash,
54
+ }
55
+ params.merge! opts
56
+
57
+ post('/api/flair', body: params)
58
+ end
59
+
60
+ # Configures flair options for a subreddit. All options are required
61
+ #
62
+ # @param enabled [true, false] Flair enabled?
63
+ # @param position [left, right] Position of user flair.
64
+ # @param self_assign [true, false] Allow users to assign their own flair from templates
65
+ # @param link_position [none, left, right] The position of link flair. Set to `none` to disable
66
+ # @param link_assign [true, false] Allow a submitter to assign their own link flair
67
+ # @param subreddit [String] The subreddit targeted.
68
+ # @return (see #clear_sessions)
69
+ def flair_config enabled, position, self_assign, link_position, link_assign, subreddit
70
+ logged_in?
71
+ # Test the params
72
+ tests = [true, false]
73
+ raise "parameter error" unless tests.include?(enabled) && tests.include?(self_assign) && tests.include?(link_assign)
74
+ tests << "none"
75
+ raise "parameter error" unless tests.include?(link_position)
76
+
77
+ post('/api/flairconfig', body: {
78
+ flair_enabled: enabled,
79
+ flair_position: position,
80
+ flair_self_assign_enabled: self_assign,
81
+ link_flair_position: link_position,
82
+ link_flair_self_assign_enabled: link_assign,
83
+ uh: @modhash,
84
+ r: subreddit
85
+ })
86
+ end
87
+
88
+ # Post flair in a CSV file to reddit
89
+ #
90
+ # @param csv [String] A string, in CSV format, of `user,flair-text,css_class` per line, with no more than 100 flairs, and **no header line**.
91
+ # @param subreddit [String] The subreddit targeted.
92
+ # @return [HTTParty::Response] The request object. Note that this request object contains a json confirming the status of each line of the CSV
93
+ def flair_csv csv, subreddit
94
+ logged_in?
95
+ post('/api/flaircsv.json', body: {flair_csv: csv, r: subreddit, uh: @modhash})
96
+ end
97
+
98
+ # Downloads flair from the subreddit
99
+ # This is limited to 1000 per request, use before/after to get "pages"
100
+ #
101
+ # @param (see #flair)
102
+ # @option opts [Fixnum] :limit (1000) The amount of flairs to get. Must be between 1 and 1000
103
+ # @option opts [String] :before Return entries just before this user id
104
+ # @option opts [String] :after Return entries just after this user id
105
+ # @return (see #clear_sessions)
106
+ def get_flair_list subreddit, opts = {}
107
+ logged_in?
108
+ raise ArgumentError, 'limit is too high/low' unless (1..1000).include?(opts[:limit]) or opts[:limit].nil?
109
+ query = {
110
+ limit: 1000,
111
+ uh: @modhash
112
+ }
113
+ query.merge! opts
114
+ get("/r/#{subreddit}/api/flairlist.json", query: query)
115
+ end
116
+
117
+ # Create or edit a flair template.
118
+ #
119
+ # @param css_class [String] The list of css classes applied to this style, space separated
120
+ # @param type [USER_FLAIR, LINK_FLAIR] The type of flair template.
121
+ # @param text [String] The flair template's text.
122
+ # @param user_editable [true, false] If the templ
123
+ # @param subreddit [String] The subreddit targeted.ate allows users to specify their own text
124
+ # @param template_id [String] The flair template ID, for editing. Get this from {#flair_template_list}
125
+ # @return (see #clear_sessions)
126
+ def flair_template css_class, type, text, user_editable, subreddit, template_id = nil
127
+ logged_in?
128
+ test = ['USER_FLAIR', 'LINK_FLAIR']
129
+ raise ArgumentError, 'type is either USER_FLAIR or LINK_FLAIR' unless test.include?(type)
130
+ test = [true, false]
131
+ raise ArgumentError, 'user_editable needs to be true or false' unless test.include?(user_editable)
132
+
133
+ params = {
134
+ css_class: css_class,
135
+ flair_type: type,
136
+ text: text,
137
+ text_editable: user_editable,
138
+ uh: @modhash,
139
+ r: subreddit
140
+ }
141
+ params[:flair_template_id] = template_id if template_id
142
+ post('/api/flairtemplate', body: params)
143
+ end
144
+
145
+ # Select a flair template and apply it to a user or link
146
+ #
147
+ # @param template_id [String] The template id to apply. Get this from {#flair_template_list}
148
+ # @param text [String] The flair text
149
+ # @param subreddit [String] The subreddit targeted.
150
+ # @param (see LinksComments#info)
151
+ # @option opts [String] :link The link id to apply to
152
+ # @option opts [String] :user The username to apply flair to
153
+ # @return (see #clear_sessions)
154
+ def select_flair_template template_id, text, subreddit, opts = {}
155
+ logged_in?
156
+ raise ArgumentError, 'link or user, not both' if link && user
157
+ params = {
158
+ flair_template_id: template_id,
159
+ text: text,
160
+ uh: @modhash,
161
+ r: subreddit
162
+ }
163
+ params.merge! opts
164
+ post('/api/selectflair', body: params)
165
+ end
166
+
167
+ # Toggle flair on and off for a subreddit
168
+ #
169
+ # @param enabled [true, false] Enable/disable flair
170
+ # @param subreddit [String] The subreddit targeted.
171
+ # @return (see #clear_sessions)
172
+ def flair_toggle enabled, subreddit
173
+ logged_in?
174
+ test = [true, false]
175
+ raise ArgumentError, 'enabled must be boolean' unless test.include?(enabled)
176
+ post('/api/setflairenabled', body: {flair_enabled: enabled, uh: @modhash, r: subreddit})
177
+ end
178
+
179
+ # @todo implement this.
180
+ # it will probably require nokogiri and some trickery.
181
+ def flair_template_list
182
+ end
183
+ end
184
+ end