redditkit 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +22 -0
- data/README.md +155 -0
- data/Rakefile +8 -0
- data/lib/redditkit.rb +26 -0
- data/lib/redditkit/base.rb +60 -0
- data/lib/redditkit/client.rb +142 -0
- data/lib/redditkit/client/account.rb +73 -0
- data/lib/redditkit/client/apps.rb +63 -0
- data/lib/redditkit/client/captcha.rb +36 -0
- data/lib/redditkit/client/comments.rb +54 -0
- data/lib/redditkit/client/flair.rb +148 -0
- data/lib/redditkit/client/links.rb +134 -0
- data/lib/redditkit/client/miscellaneous.rb +50 -0
- data/lib/redditkit/client/moderation.rb +179 -0
- data/lib/redditkit/client/multireddits.rb +207 -0
- data/lib/redditkit/client/private_messages.rb +74 -0
- data/lib/redditkit/client/search.rb +25 -0
- data/lib/redditkit/client/subreddits.rb +120 -0
- data/lib/redditkit/client/users.rb +109 -0
- data/lib/redditkit/client/utilities.rb +137 -0
- data/lib/redditkit/client/voting.rb +41 -0
- data/lib/redditkit/client/wiki.rb +83 -0
- data/lib/redditkit/comment.rb +54 -0
- data/lib/redditkit/creatable.rb +17 -0
- data/lib/redditkit/error.rb +111 -0
- data/lib/redditkit/link.rb +140 -0
- data/lib/redditkit/moderator_action.rb +19 -0
- data/lib/redditkit/multireddit.rb +32 -0
- data/lib/redditkit/multireddit_description.rb +14 -0
- data/lib/redditkit/paginated_response.rb +22 -0
- data/lib/redditkit/private_message.rb +27 -0
- data/lib/redditkit/response/parse_json.rb +29 -0
- data/lib/redditkit/response/raise_error.rb +21 -0
- data/lib/redditkit/subreddit.rb +86 -0
- data/lib/redditkit/thing.rb +20 -0
- data/lib/redditkit/user.rb +30 -0
- data/lib/redditkit/version.rb +19 -0
- data/lib/redditkit/votable.rb +37 -0
- data/redditkit.gemspec +25 -0
- data/spec/cassettes/RedditKit_Client/should_raise_an_error_with_invalid_credentials.yml +39 -0
- data/spec/cassettes/RedditKit_Client_Account/_sign_in/signs_the_user_in.yml +132 -0
- data/spec/cassettes/RedditKit_Client_Account/_update_session/updates_the_current_session.yml +133 -0
- data/spec/cassettes/RedditKit_Client_Captcha/_captcha_url/returns_a_CAPTCHA_url_from_an_identifier.yml +38 -0
- data/spec/cassettes/RedditKit_Client_Captcha/_needs_captcha_/checks_if_the_current_account_needs_a_CAPTCHA.yml +44 -0
- data/spec/cassettes/RedditKit_Client_Captcha/_new_captcha_identifier/returns_a_new_CAPTCHA_identifier.yml +38 -0
- data/spec/cassettes/RedditKit_Client_Comments/_comment/requests_the_correct_resource.yml +47 -0
- data/spec/cassettes/RedditKit_Client_Comments/_comments/with_a_RedditKit_Link/returns_comments_on_a_link.yml +140 -0
- data/spec/cassettes/RedditKit_Client_Comments/_comments/with_a_link_identifier/returns_comments_on_a_link.yml +89 -0
- data/spec/cassettes/RedditKit_Client_Comments/_submit_comment/requests_the_correct_resource.yml +313 -0
- data/spec/cassettes/RedditKit_Client_Flair/_apply_flair_template/clears_flair_templates.yml +52 -0
- data/spec/cassettes/RedditKit_Client_Flair/_clear_flair_templates/clears_flair_templates.yml +49 -0
- data/spec/cassettes/RedditKit_Client_Flair/_create_flair_template/creates_a_flair_template.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Flair/_create_flair_template/raises_InvalidClassName.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Flair/_create_flair_template/raises_TooManyClassNames.yml +47 -0
- data/spec/cassettes/RedditKit_Client_Flair/_delete_user_flair/requests_the_correct_resource.yml +60 -0
- data/spec/cassettes/RedditKit_Client_Flair/_flair_list/returns_the_list_of_flair.yml +44 -0
- data/spec/cassettes/RedditKit_Client_Flair/_set_flair/requests_the_correct_resource.yml +49 -0
- data/spec/cassettes/RedditKit_Client_Flair/_set_flair_options/sets_flair_options.yml +49 -0
- data/spec/cassettes/RedditKit_Client_Flair/_set_flair_with_csv/requests_the_correct_resource.yml +51 -0
- data/spec/cassettes/RedditKit_Client_Flair/_toggle_flair/requests_the_correct_resource.yml +49 -0
- data/spec/cassettes/RedditKit_Client_Links/_front_page/requests_the_correct_category.yml +498 -0
- data/spec/cassettes/RedditKit_Client_Links/_front_page/requests_the_correct_resource.yml +603 -0
- data/spec/cassettes/RedditKit_Client_Links/_hide/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Links/_link/returns_a_link.yml +55 -0
- data/spec/cassettes/RedditKit_Client_Links/_links/contains_pagination_information.yml +402 -0
- data/spec/cassettes/RedditKit_Client_Links/_links/requests_a_certain_number_of_links.yml +186 -0
- data/spec/cassettes/RedditKit_Client_Links/_links/requests_front_page_links_if_no_subreddit_is_present.yml +603 -0
- data/spec/cassettes/RedditKit_Client_Links/_links/requests_links_with_the_correct_time_frame.yml +375 -0
- data/spec/cassettes/RedditKit_Client_Links/_links/requests_the_correct_subreddit_and_category.yml +402 -0
- data/spec/cassettes/RedditKit_Client_Links/_links_with_domain/returns_links_with_a_specific_domain.yml +99 -0
- data/spec/cassettes/RedditKit_Client_Links/_mark_nsfw/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Links/_random_link/returns_a_random_link.yml +91 -0
- data/spec/cassettes/RedditKit_Client_Links/_submit/raises_RedditKit_InvalidCaptcha_if_no_CAPTCHA_is_filled_out.yml +54 -0
- data/spec/cassettes/RedditKit_Client_Links/_unhide/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Links/_unmark_nsfw/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Miscellaneous/_delete/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Miscellaneous/_edit/requests_the_correct_resource.yml +52 -0
- data/spec/cassettes/RedditKit_Client_Miscellaneous/_save/saves_an_object.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Miscellaneous/_unsave/unsaves_an_object.yml +89 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_accept_moderator_invitation/requests_the_correct_resource.yml +53 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_ban/requests_the_correct_resource.yml +103 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_contributors_to_subreddit/requests_the_correct_resource.yml +47 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_ignore_reports/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_moderation_log/returns_RedditKit_ModeratorAction_objects.yml +153 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_moderators_of_subreddit/requests_the_correct_resource.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_reset_subreddit_header/requests_the_correct_resource.yml +55 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_set_contest_mode/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_set_sticky_post/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_unban/requests_the_correct_resource.yml +54 -0
- data/spec/cassettes/RedditKit_Client_Moderation/_unignore_reports/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_add_subreddit_to_multireddit/adds_a_subreddit_to_a_multireddit.yml +177 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_create_multireddit/creates_a_multireddit.yml +137 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_create_multireddit/raises_RedditKit_Conflict_when_using_an_existing_name.yml +133 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_delete_multireddit/deletes_a_multireddit.yml +134 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit/with_a_path/returns_a_multireddit.yml +39 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit/without_a_path/returns_a_multireddit.yml +39 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit_description/with_a_multireddit/returns_a_multireddit_description.yml +81 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit_description/with_a_username_and_multireddit_name/returns_a_multireddit_description.yml +45 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_my_multireddits/return_s_the_user_s_multireddits.yml +47 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_remove_subreddit_from_multireddit/removes_a_subreddit_from_a_multireddit.yml +175 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_rename_multireddit/renames_a_multireddit.yml +134 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_set_multireddit_description/returns_a_multireddit_description.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Multireddits/_update_multireddit/updates_a_multireddit.yml +184 -0
- data/spec/cassettes/RedditKit_Client_PrivateMessages/_block_author_of_message/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_PrivateMessages/_mark_as_read/requests_the_correct_resource.yml +51 -0
- data/spec/cassettes/RedditKit_Client_PrivateMessages/_mark_as_unread/requests_the_correct_resource.yml +51 -0
- data/spec/cassettes/RedditKit_Client_PrivateMessages/_messages/requests_the_correct_resource.yml +187 -0
- data/spec/cassettes/RedditKit_Client_PrivateMessages/_unblock/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Search/_search/restricts_searches_to_a_specific_subreddit.yml +878 -0
- data/spec/cassettes/RedditKit_Client_Search/_search/returns_a_specific_number_of_results.yml +130 -0
- data/spec/cassettes/RedditKit_Client_Search/_search/returns_search_results.yml +844 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_random_subreddit/returns_a_random_subreddit.yml +181 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_recommended_subreddits/returns_subreddit_names.yml +37 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_search_subreddits_by_name/returns_subreddit_names.yml +875 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subreddit/returns_a_specified_subreddit.yml +100 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subreddits/returns_a_specified_number_of_subreddits.yml +505 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subreddits/returns_subreddits_from_a_specific_category.yml +510 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subreddits_by_topic/returns_subreddit_names.yml +41 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subscribe/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subscribed_subreddits/returns_a_specified_number_of_subreddits.yml +415 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subscribed_subreddits/returns_subreddits_from_a_specific_category.yml +58 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_subscribed_subreddits/returns_the_user_s_subscribed_subreddits.yml +3469 -0
- data/spec/cassettes/RedditKit_Client_Subreddits/_unsubscribe/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Users/_friends/returns_the_user_s_friends.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Users/_my_content/returns_the_user_s_content.yml +60 -0
- data/spec/cassettes/RedditKit_Client_Users/_user/requests_the_correct_resource.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Users/_user/returns_a_specified_user.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Users/_user/returns_the_authenticated_user.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Users/_user_content/returns_the_user_s_content.yml +41 -0
- data/spec/cassettes/RedditKit_Client_Users/_username_available_/returns_false_for_an_unavailable_username.yml +36 -0
- data/spec/cassettes/RedditKit_Client_Users/_username_available_/returns_true_for_an_available_username.yml +36 -0
- data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_comment_full_name_passed/downvotes_the_comment.yml +100 -0
- data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_comment_passed/downvotes_the_comment.yml +154 -0
- data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_link_full_name_passed/downvotes_the_link.yml +106 -0
- data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_link_passed/downvotes_the_link.yml +166 -0
- data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_comment_full_name_passed/upvotes_the_comment.yml +100 -0
- data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_comment_passed/upvotes_the_comment.yml +154 -0
- data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_link_full_name_passed/upvotes_the_link.yml +106 -0
- data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_link_passed/upvotes_the_link.yml +166 -0
- data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_comment_full_name_passed/withdraws_the_vote_on_the_comment.yml +154 -0
- data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_comment_passed/withdraws_the_vote_on_the_comment.yml +208 -0
- data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_link_full_name_passed/withdraws_the_vote_on_the_link.yml +166 -0
- data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_link_passed/withdraws_the_vote_on_the_link.yml +226 -0
- data/spec/cassettes/RedditKit_Client_Wiki/_add_wiki_editor/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Wiki/_edit_wiki_page/requests_the_correct_resource.yml +48 -0
- data/spec/cassettes/RedditKit_Client_Wiki/_hide_wiki_revision/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Wiki/_remove_wiki_editor/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Client_Wiki/_revert_to_revision/requests_the_correct_resource.yml +46 -0
- data/spec/cassettes/RedditKit_Comment/should_not_be_deleted_if_neither_author_and_comment_attributes_are_set_to_deleted_.yml +90 -0
- data/spec/cassettes/RedditKit_Comment/should_return_replies.yml +90 -0
- data/spec/cassettes/authenticated_client.yml +87 -0
- data/spec/redditkit/base_spec.rb +45 -0
- data/spec/redditkit/client/account_spec.rb +50 -0
- data/spec/redditkit/client/apps_spec.rb +58 -0
- data/spec/redditkit/client/captcha_spec.rb +30 -0
- data/spec/redditkit/client/comments_spec.rb +40 -0
- data/spec/redditkit/client/flair_spec.rb +92 -0
- data/spec/redditkit/client/links_spec.rb +103 -0
- data/spec/redditkit/client/miscellaneous_spec.rb +40 -0
- data/spec/redditkit/client/moderation_spec.rb +141 -0
- data/spec/redditkit/client/multireddits_spec.rb +158 -0
- data/spec/redditkit/client/private_messages_spec.rb +51 -0
- data/spec/redditkit/client/search_spec.rb +25 -0
- data/spec/redditkit/client/subreddits_spec.rb +83 -0
- data/spec/redditkit/client/users_spec.rb +92 -0
- data/spec/redditkit/client/voting_spec.rb +99 -0
- data/spec/redditkit/client/wiki_spec.rb +40 -0
- data/spec/redditkit/client_spec.rb +46 -0
- data/spec/redditkit/comment_spec.rb +26 -0
- data/spec/redditkit/creatable_spec.rb +24 -0
- data/spec/redditkit/error_spec.rb +61 -0
- data/spec/redditkit/link_spec.rb +33 -0
- data/spec/redditkit/multireddit_spec.rb +27 -0
- data/spec/redditkit/paginated_response_spec.rb +23 -0
- data/spec/redditkit/thing_spec.rb +18 -0
- data/spec/redditkit/votable_spec.rb +52 -0
- data/spec/redditkit_spec.rb +21 -0
- data/spec/spec_helper.rb +124 -0
- metadata +390 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bf49ee7e4888671f3860d38d4a794b6594207827
|
4
|
+
data.tar.gz: 9495006c5cc268dd6df62780c97017521239c17f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d9e8b304a65560e2df483a9b0b55bfb8811647691e61afdb71ed454e7653fee11e8db600e28c23d6f944ff634e30d9d32a422994abe9fc96de9d8e143d9d59d6
|
7
|
+
data.tar.gz: b5fbc3f4729e5ed803d029d206369ff80132d697f73cd099fdb56fab15aaad9b0a049b84c7e548f0ebe29e57f5f791e57616c0b8661399cec172cea4f45c296c
|
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sam Symons
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
# RedditKit.rb
|
2
|
+
|
3
|
+
RedditKit.rb is a [reddit API](http://www.reddit.com/dev/api) wrapper, written in Ruby.
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/samsymons/RedditKit.rb.png?branch=master)][travis]
|
6
|
+
[![Code Climate](https://codeclimate.com/github/samsymons/RedditKit.rb.png)][codeclimate]
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/samsymons/RedditKit.rb/badge.png?branch=master)][coveralls]
|
8
|
+
|
9
|
+
[travis]: http://travis-ci.org/samsymons/RedditKit.rb
|
10
|
+
[codeclimate]: https://codeclimate.com/github/samsymons/RedditKit.rb
|
11
|
+
[coveralls]: https://coveralls.io/r/samsymons/RedditKit.rb
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this to your Gemfile:
|
16
|
+
|
17
|
+
gem 'redditkit', '~> 1.0'
|
18
|
+
|
19
|
+
Or install it directly:
|
20
|
+
|
21
|
+
gem install redditkit
|
22
|
+
|
23
|
+
## Getting Started
|
24
|
+
|
25
|
+
RedditKit.rb is structured closely to the wonderful [Octokit.rb](https://github.com/octokit/octokit.rb) and [Twitter](https://github.com/sferik/twitter) gems. If you're familiar with either of those, you'll feel right at home here. You can find the [project's documentation on the RedditKit website](http://redditkit.com/redditkit.rb/).
|
26
|
+
|
27
|
+
RedditKit.rb is used through either the `RedditKit` module, or `RedditKit::Client` objects, like so:
|
28
|
+
|
29
|
+
**Module usage:**
|
30
|
+
```ruby
|
31
|
+
RedditKit.sign_in 'username', 'password'
|
32
|
+
subreddits = RedditKit.subscribed_subreddits
|
33
|
+
```
|
34
|
+
|
35
|
+
**Instance method usage:**
|
36
|
+
```ruby
|
37
|
+
client = RedditKit::Client.new 'username', 'password'
|
38
|
+
subreddits = client.subscribed_subreddits
|
39
|
+
```
|
40
|
+
|
41
|
+
Using RedditKit.rb at the module level allows you to use a single account without having to keep track of RedditKit::Client instances. Working at the instance method level makes it possible to use multiple accounts at once, with one client object per account.
|
42
|
+
|
43
|
+
> RedditKit.rb doesn't have any built-in rate limiting. reddit's API rules require that you make no more than 30 requests per minute and try to avoid requesting the same page more than once every 30 seconds. You can read up on the API rules [on their wiki page](https://github.com/reddit/reddit/wiki/API).
|
44
|
+
|
45
|
+
### Authentication
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
client = RedditKit::Client.new 'username', 'password'
|
49
|
+
client.signed_in? # => true
|
50
|
+
```
|
51
|
+
|
52
|
+
## More Examples
|
53
|
+
|
54
|
+
**Fetch a user and check their link karma:**
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
user = RedditKit.user 'samsymons'
|
58
|
+
puts "#{user.username} has #{user.link_karma} link karma."
|
59
|
+
```
|
60
|
+
|
61
|
+
**Subscribe to a subreddit:**
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
authenticated_client = RedditKit::Client.new 'samsymons', 'password'
|
65
|
+
authenticated_client.subscribe 'ruby'
|
66
|
+
```
|
67
|
+
|
68
|
+
**Upvote the top post in a subreddit:**
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
posts = authenticated_client.posts 'programming', :category => :top, :time => :all
|
72
|
+
authenticated_client.upvote posts.first
|
73
|
+
```
|
74
|
+
|
75
|
+
**Send private messages:**
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
authenticated_client.send_message 'How are you?', 'amberlynns', :subject => 'Hi!'
|
79
|
+
```
|
80
|
+
|
81
|
+
## Pagination
|
82
|
+
|
83
|
+
Some RedditKit.rb methods accept pagination options and return `RedditKit::PaginatedResponse` objects upon completion. These options allow you to, for example, limit the number of results returned, or fetch results before/after a specific object.
|
84
|
+
|
85
|
+
`RedditKit::PaginatedResponse` forwards its enumeration methods to its `results` array, so you can iterate over it like you would with a standard array.
|
86
|
+
|
87
|
+
``` ruby
|
88
|
+
paginated_response = RedditKit.front_page
|
89
|
+
|
90
|
+
paginated_response.each do |link|
|
91
|
+
# Do something with each link.
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
## Multiple Accounts
|
96
|
+
|
97
|
+
## Configuration
|
98
|
+
|
99
|
+
You can configure various aspects of RedditKit.rb's operation, including its default API endpoint and user agent, by setting attributes on `RedditKit::Client`.
|
100
|
+
|
101
|
+
**You should set your user agent to the name and version of your app, along with your reddit username. That way, if you ever have a buggy version of your app abusing the API, the reddit admins will know who to contact.**
|
102
|
+
|
103
|
+
## Contributing
|
104
|
+
|
105
|
+
### Debugging
|
106
|
+
|
107
|
+
Because RedditKit.rb is built atop Faraday, you can modify its middleware stack to add new behaviour. This is particularly handy for debugging as you can turn on Faraday's response logger.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
RedditKit.middleware = Faraday::Builder.new do |builder|
|
111
|
+
builder.use Faraday::Request::UrlEncoded
|
112
|
+
builder.use RedditKit::Response::RaiseError
|
113
|
+
builder.use RedditKit::Response::ParseJSON
|
114
|
+
builder.use Faraday::Response::Logger
|
115
|
+
builder.adapter Faraday.default_adapter
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
### Writing Tests
|
120
|
+
|
121
|
+
Tests assume the presence of a `.env` file at the project's root. This file should contain the following three environment variables:
|
122
|
+
|
123
|
+
* `REDDITKIT_TEST_USERNAME` The username of a reddit account dedicated solely to testing.
|
124
|
+
* `REDDITKIT_TEST_PASSWORD` The password for the reddit account.
|
125
|
+
* `REDDITKIT_TEST_SUBREDDIT` A subreddit for which the provided reddit account has admin privileges. This subreddit should be also be dedicated to testing as the test suite will run many different methods on it, creating & deleting various resources.
|
126
|
+
|
127
|
+
## Requirements
|
128
|
+
|
129
|
+
Ruby 1.9.3 and Ruby 2.0.0 are officially supported.
|
130
|
+
|
131
|
+
## Need Help?
|
132
|
+
|
133
|
+
Open an [issue](https://github.com/samsymons/RedditKit.rb/issues), or hit me up on [Twitter](http://twitter.com/sam_symons).
|
134
|
+
|
135
|
+
## License
|
136
|
+
|
137
|
+
Copyright (c) 2013 Sam Symons (http://samsymons.com/)
|
138
|
+
|
139
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
140
|
+
of this software and associated documentation files (the "Software"), to deal
|
141
|
+
in the Software without restriction, including without limitation the rights
|
142
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
143
|
+
copies of the Software, and to permit persons to whom the Software is
|
144
|
+
furnished to do so, subject to the following conditions:
|
145
|
+
|
146
|
+
The above copyright notice and this permission notice shall be included in
|
147
|
+
all copies or substantial portions of the Software.
|
148
|
+
|
149
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
150
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
151
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
152
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
153
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
154
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
155
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
data/lib/redditkit.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'redditkit/client'
|
2
|
+
|
3
|
+
# The main RedditKit module.
|
4
|
+
module RedditKit
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# A RedditKit::Client, used when calling methods on the RedditKit module itself.
|
8
|
+
#
|
9
|
+
# @return [RedditKit::Client]
|
10
|
+
def client
|
11
|
+
@client ||= RedditKit::Client.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def respond_to?(method_name, include_private = false)
|
15
|
+
client.respond_to?(method_name, include_private) || super
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def method_missing(method_name, *args, &block)
|
21
|
+
return super unless client.respond_to?(method_name)
|
22
|
+
client.send(method_name, *args, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module RedditKit
|
2
|
+
|
3
|
+
# A base class for RedditKit's model objects, automatically generating attribute and predicate methods.
|
4
|
+
class Base
|
5
|
+
|
6
|
+
attr_reader :attributes
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def attr_reader(*attrs)
|
11
|
+
attrs.each do |attr|
|
12
|
+
define_attribute_method(attr)
|
13
|
+
define_predicate_method(attr)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def define_attribute_method(method)
|
20
|
+
define_method(method) do
|
21
|
+
memoize(method) do
|
22
|
+
@attributes[method]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def define_predicate_method(method)
|
28
|
+
define_method(:"#{method}?") do
|
29
|
+
!!@attributes[method]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(attributes = {})
|
36
|
+
kind = attributes[:kind]
|
37
|
+
data = attributes[:data]
|
38
|
+
|
39
|
+
@attributes = data || {}
|
40
|
+
@attributes[:kind] = kind
|
41
|
+
end
|
42
|
+
|
43
|
+
def [](method)
|
44
|
+
send(method.to_sym)
|
45
|
+
rescue NoMethodError
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def memoize(key, &block)
|
52
|
+
ivar = :"@#{key}"
|
53
|
+
return instance_variable_get(ivar) if instance_variable_defined?(ivar)
|
54
|
+
|
55
|
+
result = block.call
|
56
|
+
instance_variable_set(ivar, result)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'redditkit/error'
|
3
|
+
require 'redditkit/version'
|
4
|
+
require 'redditkit/client/account'
|
5
|
+
require 'redditkit/client/apps'
|
6
|
+
require 'redditkit/client/captcha'
|
7
|
+
require 'redditkit/client/comments'
|
8
|
+
require 'redditkit/client/flair'
|
9
|
+
require 'redditkit/client/links'
|
10
|
+
require 'redditkit/client/miscellaneous'
|
11
|
+
require 'redditkit/client/moderation'
|
12
|
+
require 'redditkit/client/multireddits'
|
13
|
+
require 'redditkit/client/private_messages'
|
14
|
+
require 'redditkit/client/search'
|
15
|
+
require 'redditkit/client/subreddits'
|
16
|
+
require 'redditkit/client/users'
|
17
|
+
require 'redditkit/client/utilities'
|
18
|
+
require 'redditkit/client/voting'
|
19
|
+
require 'redditkit/client/wiki'
|
20
|
+
require 'redditkit/response/parse_json'
|
21
|
+
require 'redditkit/response/raise_error'
|
22
|
+
|
23
|
+
module RedditKit
|
24
|
+
|
25
|
+
# The client for the reddit API, handling all interactions with reddit's servers.
|
26
|
+
class Client
|
27
|
+
include RedditKit::Client::Account
|
28
|
+
include RedditKit::Client::Apps
|
29
|
+
include RedditKit::Client::Captcha
|
30
|
+
include RedditKit::Client::Comments
|
31
|
+
include RedditKit::Client::Flair
|
32
|
+
include RedditKit::Client::Links
|
33
|
+
include RedditKit::Client::Miscellaneous
|
34
|
+
include RedditKit::Client::Moderation
|
35
|
+
include RedditKit::Client::Multireddits
|
36
|
+
include RedditKit::Client::PrivateMessages
|
37
|
+
include RedditKit::Client::Search
|
38
|
+
include RedditKit::Client::Subreddits
|
39
|
+
include RedditKit::Client::Users
|
40
|
+
include RedditKit::Client::Utilities
|
41
|
+
include RedditKit::Client::Voting
|
42
|
+
include RedditKit::Client::Wiki
|
43
|
+
|
44
|
+
attr_reader :username
|
45
|
+
attr_reader :current_user
|
46
|
+
attr_reader :cookie
|
47
|
+
attr_reader :modhash
|
48
|
+
|
49
|
+
attr_accessor :api_endpoint
|
50
|
+
attr_accessor :authentication_endpoint
|
51
|
+
attr_accessor :user_agent
|
52
|
+
attr_accessor :middleware
|
53
|
+
|
54
|
+
def initialize(username = nil, password = nil)
|
55
|
+
@username = username
|
56
|
+
@password = password
|
57
|
+
|
58
|
+
@cookie = nil
|
59
|
+
@modhash = nil
|
60
|
+
|
61
|
+
unless @username.nil? or @password.nil?
|
62
|
+
sign_in @username, @password
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def api_endpoint
|
67
|
+
@api_endpoint ||= 'http://www.reddit.com/'
|
68
|
+
end
|
69
|
+
|
70
|
+
def authentication_endpoint
|
71
|
+
@authentication_endpoint ||= 'https://ssl.reddit.com/'
|
72
|
+
end
|
73
|
+
|
74
|
+
def user_agent
|
75
|
+
@user_agent ||= "RedditKit.rb #{RedditKit::Version.to_s}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def middleware
|
79
|
+
@middleware ||= Faraday::Builder.new do |builder|
|
80
|
+
builder.use Faraday::Request::UrlEncoded
|
81
|
+
builder.use RedditKit::Response::RaiseError
|
82
|
+
builder.use RedditKit::Response::ParseJSON
|
83
|
+
builder.adapter Faraday.default_adapter
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def get(path, params = nil)
|
90
|
+
request(:get, path, params, connection)
|
91
|
+
end
|
92
|
+
|
93
|
+
def post(path, params = nil)
|
94
|
+
request(:post, path, params, connection)
|
95
|
+
end
|
96
|
+
|
97
|
+
def https_post(path, params = nil)
|
98
|
+
request(:post, path, params, https_connection)
|
99
|
+
end
|
100
|
+
|
101
|
+
def put(path, params = nil)
|
102
|
+
request(:put, path, params, connection)
|
103
|
+
end
|
104
|
+
|
105
|
+
def delete_path(path, params = nil)
|
106
|
+
request(:delete, path, params, connection)
|
107
|
+
end
|
108
|
+
|
109
|
+
def request(method, path, parameters = {}, request_connection)
|
110
|
+
if signed_in?
|
111
|
+
request = authenticated_request_configuration(method, path, parameters)
|
112
|
+
request_connection.send(method.to_sym, path, parameters, &request).env
|
113
|
+
else
|
114
|
+
request_connection.send(method.to_sym, path, parameters).env
|
115
|
+
end
|
116
|
+
rescue Faraday::Error::ClientError
|
117
|
+
raise RedditKit::RequestError
|
118
|
+
end
|
119
|
+
|
120
|
+
def authenticated_request_configuration(method, path, parameters)
|
121
|
+
raise RedditKit::NotAuthenticated unless signed_in?
|
122
|
+
|
123
|
+
Proc.new do |request|
|
124
|
+
request.headers['Cookie'] = "reddit_session=#{@cookie}"
|
125
|
+
request.headers['X-Modhash'] = @modhash
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def connection
|
130
|
+
@connection ||= connection_with_url(api_endpoint)
|
131
|
+
end
|
132
|
+
|
133
|
+
def https_connection
|
134
|
+
@https_connection ||= connection_with_url(authentication_endpoint)
|
135
|
+
end
|
136
|
+
|
137
|
+
def connection_with_url(url)
|
138
|
+
Faraday.new(url, { :builder => middleware })
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module RedditKit
|
2
|
+
class Client
|
3
|
+
|
4
|
+
# Methods which operate on a user's account.
|
5
|
+
module Account
|
6
|
+
|
7
|
+
# Sign in to a reddit account.
|
8
|
+
#
|
9
|
+
# @see http://www.reddit.com/dev/api#POST_api_login
|
10
|
+
# @param username [String] The reddit account's username.
|
11
|
+
# @param password [String] The reddit account's password.
|
12
|
+
def sign_in(username, password)
|
13
|
+
response = https_post 'api/login', { :user => username, :passwd => password, :api_type => :json }
|
14
|
+
body = response[:body]
|
15
|
+
|
16
|
+
data = body[:json][:data]
|
17
|
+
|
18
|
+
@modhash = data[:modhash]
|
19
|
+
@cookie = data[:cookie]
|
20
|
+
@username = username
|
21
|
+
|
22
|
+
@current_user = user @username
|
23
|
+
@username = @current_user.username
|
24
|
+
end
|
25
|
+
|
26
|
+
# Check is a user is currently signed in.
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
def signed_in?
|
30
|
+
!!@modhash and !!@cookie
|
31
|
+
end
|
32
|
+
|
33
|
+
# Sign the current user out.
|
34
|
+
def sign_out
|
35
|
+
@username = nil
|
36
|
+
@current_user = nil
|
37
|
+
|
38
|
+
@modhash = nil
|
39
|
+
@cookie = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Updates the current user's email or password.
|
43
|
+
#
|
44
|
+
# @see http://www.reddit.com/dev/api#POST_api_update
|
45
|
+
# @option options [String] current_password The user's current password.
|
46
|
+
# @option options [String] new_password The user's new password.
|
47
|
+
# @option options [String] email The user's new email address.
|
48
|
+
def update_account(options)
|
49
|
+
password = options[:new_password]
|
50
|
+
parameters = { :curpass => options[:current_password], :email => options[:email], :newpass => password, :verpass => password, :api_type => :json }
|
51
|
+
|
52
|
+
post('api/update', parameters)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Invalidates all session cookies and updates the current one.
|
56
|
+
#
|
57
|
+
# @see http://www.reddit.com/dev/api#POST_api_clear_sessions
|
58
|
+
# @param password [String] The authenticated user's current password.
|
59
|
+
# @return [String] The new cookie value.
|
60
|
+
def update_session(password)
|
61
|
+
response = post('api/clear_sessions', :dest => api_endpoint, :curpass => password, :api_type => 'json')
|
62
|
+
|
63
|
+
response_headers = response[:response_headers]
|
64
|
+
full_cookie_string = response_headers['set-cookie']
|
65
|
+
cookie = full_cookie_string[/reddit_session=(.*?);/m, 1]
|
66
|
+
|
67
|
+
@cookie = cookie
|
68
|
+
cookie
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|