redditkit 1.0.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.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +22 -0
  3. data/README.md +155 -0
  4. data/Rakefile +8 -0
  5. data/lib/redditkit.rb +26 -0
  6. data/lib/redditkit/base.rb +60 -0
  7. data/lib/redditkit/client.rb +142 -0
  8. data/lib/redditkit/client/account.rb +73 -0
  9. data/lib/redditkit/client/apps.rb +63 -0
  10. data/lib/redditkit/client/captcha.rb +36 -0
  11. data/lib/redditkit/client/comments.rb +54 -0
  12. data/lib/redditkit/client/flair.rb +148 -0
  13. data/lib/redditkit/client/links.rb +134 -0
  14. data/lib/redditkit/client/miscellaneous.rb +50 -0
  15. data/lib/redditkit/client/moderation.rb +179 -0
  16. data/lib/redditkit/client/multireddits.rb +207 -0
  17. data/lib/redditkit/client/private_messages.rb +74 -0
  18. data/lib/redditkit/client/search.rb +25 -0
  19. data/lib/redditkit/client/subreddits.rb +120 -0
  20. data/lib/redditkit/client/users.rb +109 -0
  21. data/lib/redditkit/client/utilities.rb +137 -0
  22. data/lib/redditkit/client/voting.rb +41 -0
  23. data/lib/redditkit/client/wiki.rb +83 -0
  24. data/lib/redditkit/comment.rb +54 -0
  25. data/lib/redditkit/creatable.rb +17 -0
  26. data/lib/redditkit/error.rb +111 -0
  27. data/lib/redditkit/link.rb +140 -0
  28. data/lib/redditkit/moderator_action.rb +19 -0
  29. data/lib/redditkit/multireddit.rb +32 -0
  30. data/lib/redditkit/multireddit_description.rb +14 -0
  31. data/lib/redditkit/paginated_response.rb +22 -0
  32. data/lib/redditkit/private_message.rb +27 -0
  33. data/lib/redditkit/response/parse_json.rb +29 -0
  34. data/lib/redditkit/response/raise_error.rb +21 -0
  35. data/lib/redditkit/subreddit.rb +86 -0
  36. data/lib/redditkit/thing.rb +20 -0
  37. data/lib/redditkit/user.rb +30 -0
  38. data/lib/redditkit/version.rb +19 -0
  39. data/lib/redditkit/votable.rb +37 -0
  40. data/redditkit.gemspec +25 -0
  41. data/spec/cassettes/RedditKit_Client/should_raise_an_error_with_invalid_credentials.yml +39 -0
  42. data/spec/cassettes/RedditKit_Client_Account/_sign_in/signs_the_user_in.yml +132 -0
  43. data/spec/cassettes/RedditKit_Client_Account/_update_session/updates_the_current_session.yml +133 -0
  44. data/spec/cassettes/RedditKit_Client_Captcha/_captcha_url/returns_a_CAPTCHA_url_from_an_identifier.yml +38 -0
  45. data/spec/cassettes/RedditKit_Client_Captcha/_needs_captcha_/checks_if_the_current_account_needs_a_CAPTCHA.yml +44 -0
  46. data/spec/cassettes/RedditKit_Client_Captcha/_new_captcha_identifier/returns_a_new_CAPTCHA_identifier.yml +38 -0
  47. data/spec/cassettes/RedditKit_Client_Comments/_comment/requests_the_correct_resource.yml +47 -0
  48. data/spec/cassettes/RedditKit_Client_Comments/_comments/with_a_RedditKit_Link/returns_comments_on_a_link.yml +140 -0
  49. data/spec/cassettes/RedditKit_Client_Comments/_comments/with_a_link_identifier/returns_comments_on_a_link.yml +89 -0
  50. data/spec/cassettes/RedditKit_Client_Comments/_submit_comment/requests_the_correct_resource.yml +313 -0
  51. data/spec/cassettes/RedditKit_Client_Flair/_apply_flair_template/clears_flair_templates.yml +52 -0
  52. data/spec/cassettes/RedditKit_Client_Flair/_clear_flair_templates/clears_flair_templates.yml +49 -0
  53. data/spec/cassettes/RedditKit_Client_Flair/_create_flair_template/creates_a_flair_template.yml +46 -0
  54. data/spec/cassettes/RedditKit_Client_Flair/_create_flair_template/raises_InvalidClassName.yml +46 -0
  55. data/spec/cassettes/RedditKit_Client_Flair/_create_flair_template/raises_TooManyClassNames.yml +47 -0
  56. data/spec/cassettes/RedditKit_Client_Flair/_delete_user_flair/requests_the_correct_resource.yml +60 -0
  57. data/spec/cassettes/RedditKit_Client_Flair/_flair_list/returns_the_list_of_flair.yml +44 -0
  58. data/spec/cassettes/RedditKit_Client_Flair/_set_flair/requests_the_correct_resource.yml +49 -0
  59. data/spec/cassettes/RedditKit_Client_Flair/_set_flair_options/sets_flair_options.yml +49 -0
  60. data/spec/cassettes/RedditKit_Client_Flair/_set_flair_with_csv/requests_the_correct_resource.yml +51 -0
  61. data/spec/cassettes/RedditKit_Client_Flair/_toggle_flair/requests_the_correct_resource.yml +49 -0
  62. data/spec/cassettes/RedditKit_Client_Links/_front_page/requests_the_correct_category.yml +498 -0
  63. data/spec/cassettes/RedditKit_Client_Links/_front_page/requests_the_correct_resource.yml +603 -0
  64. data/spec/cassettes/RedditKit_Client_Links/_hide/requests_the_correct_resource.yml +46 -0
  65. data/spec/cassettes/RedditKit_Client_Links/_link/returns_a_link.yml +55 -0
  66. data/spec/cassettes/RedditKit_Client_Links/_links/contains_pagination_information.yml +402 -0
  67. data/spec/cassettes/RedditKit_Client_Links/_links/requests_a_certain_number_of_links.yml +186 -0
  68. data/spec/cassettes/RedditKit_Client_Links/_links/requests_front_page_links_if_no_subreddit_is_present.yml +603 -0
  69. data/spec/cassettes/RedditKit_Client_Links/_links/requests_links_with_the_correct_time_frame.yml +375 -0
  70. data/spec/cassettes/RedditKit_Client_Links/_links/requests_the_correct_subreddit_and_category.yml +402 -0
  71. data/spec/cassettes/RedditKit_Client_Links/_links_with_domain/returns_links_with_a_specific_domain.yml +99 -0
  72. data/spec/cassettes/RedditKit_Client_Links/_mark_nsfw/requests_the_correct_resource.yml +46 -0
  73. data/spec/cassettes/RedditKit_Client_Links/_random_link/returns_a_random_link.yml +91 -0
  74. data/spec/cassettes/RedditKit_Client_Links/_submit/raises_RedditKit_InvalidCaptcha_if_no_CAPTCHA_is_filled_out.yml +54 -0
  75. data/spec/cassettes/RedditKit_Client_Links/_unhide/requests_the_correct_resource.yml +46 -0
  76. data/spec/cassettes/RedditKit_Client_Links/_unmark_nsfw/requests_the_correct_resource.yml +46 -0
  77. data/spec/cassettes/RedditKit_Client_Miscellaneous/_delete/requests_the_correct_resource.yml +46 -0
  78. data/spec/cassettes/RedditKit_Client_Miscellaneous/_edit/requests_the_correct_resource.yml +52 -0
  79. data/spec/cassettes/RedditKit_Client_Miscellaneous/_save/saves_an_object.yml +46 -0
  80. data/spec/cassettes/RedditKit_Client_Miscellaneous/_unsave/unsaves_an_object.yml +89 -0
  81. data/spec/cassettes/RedditKit_Client_Moderation/_accept_moderator_invitation/requests_the_correct_resource.yml +53 -0
  82. data/spec/cassettes/RedditKit_Client_Moderation/_ban/requests_the_correct_resource.yml +103 -0
  83. data/spec/cassettes/RedditKit_Client_Moderation/_contributors_to_subreddit/requests_the_correct_resource.yml +47 -0
  84. data/spec/cassettes/RedditKit_Client_Moderation/_ignore_reports/requests_the_correct_resource.yml +46 -0
  85. data/spec/cassettes/RedditKit_Client_Moderation/_moderation_log/returns_RedditKit_ModeratorAction_objects.yml +153 -0
  86. data/spec/cassettes/RedditKit_Client_Moderation/_moderators_of_subreddit/requests_the_correct_resource.yml +48 -0
  87. data/spec/cassettes/RedditKit_Client_Moderation/_reset_subreddit_header/requests_the_correct_resource.yml +55 -0
  88. data/spec/cassettes/RedditKit_Client_Moderation/_set_contest_mode/requests_the_correct_resource.yml +46 -0
  89. data/spec/cassettes/RedditKit_Client_Moderation/_set_sticky_post/requests_the_correct_resource.yml +46 -0
  90. data/spec/cassettes/RedditKit_Client_Moderation/_unban/requests_the_correct_resource.yml +54 -0
  91. data/spec/cassettes/RedditKit_Client_Moderation/_unignore_reports/requests_the_correct_resource.yml +46 -0
  92. data/spec/cassettes/RedditKit_Client_Multireddits/_add_subreddit_to_multireddit/adds_a_subreddit_to_a_multireddit.yml +177 -0
  93. data/spec/cassettes/RedditKit_Client_Multireddits/_create_multireddit/creates_a_multireddit.yml +137 -0
  94. data/spec/cassettes/RedditKit_Client_Multireddits/_create_multireddit/raises_RedditKit_Conflict_when_using_an_existing_name.yml +133 -0
  95. data/spec/cassettes/RedditKit_Client_Multireddits/_delete_multireddit/deletes_a_multireddit.yml +134 -0
  96. data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit/with_a_path/returns_a_multireddit.yml +39 -0
  97. data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit/without_a_path/returns_a_multireddit.yml +39 -0
  98. data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit_description/with_a_multireddit/returns_a_multireddit_description.yml +81 -0
  99. data/spec/cassettes/RedditKit_Client_Multireddits/_multireddit_description/with_a_username_and_multireddit_name/returns_a_multireddit_description.yml +45 -0
  100. data/spec/cassettes/RedditKit_Client_Multireddits/_my_multireddits/return_s_the_user_s_multireddits.yml +47 -0
  101. data/spec/cassettes/RedditKit_Client_Multireddits/_remove_subreddit_from_multireddit/removes_a_subreddit_from_a_multireddit.yml +175 -0
  102. data/spec/cassettes/RedditKit_Client_Multireddits/_rename_multireddit/renames_a_multireddit.yml +134 -0
  103. data/spec/cassettes/RedditKit_Client_Multireddits/_set_multireddit_description/returns_a_multireddit_description.yml +48 -0
  104. data/spec/cassettes/RedditKit_Client_Multireddits/_update_multireddit/updates_a_multireddit.yml +184 -0
  105. data/spec/cassettes/RedditKit_Client_PrivateMessages/_block_author_of_message/requests_the_correct_resource.yml +46 -0
  106. data/spec/cassettes/RedditKit_Client_PrivateMessages/_mark_as_read/requests_the_correct_resource.yml +51 -0
  107. data/spec/cassettes/RedditKit_Client_PrivateMessages/_mark_as_unread/requests_the_correct_resource.yml +51 -0
  108. data/spec/cassettes/RedditKit_Client_PrivateMessages/_messages/requests_the_correct_resource.yml +187 -0
  109. data/spec/cassettes/RedditKit_Client_PrivateMessages/_unblock/requests_the_correct_resource.yml +46 -0
  110. data/spec/cassettes/RedditKit_Client_Search/_search/restricts_searches_to_a_specific_subreddit.yml +878 -0
  111. data/spec/cassettes/RedditKit_Client_Search/_search/returns_a_specific_number_of_results.yml +130 -0
  112. data/spec/cassettes/RedditKit_Client_Search/_search/returns_search_results.yml +844 -0
  113. data/spec/cassettes/RedditKit_Client_Subreddits/_random_subreddit/returns_a_random_subreddit.yml +181 -0
  114. data/spec/cassettes/RedditKit_Client_Subreddits/_recommended_subreddits/returns_subreddit_names.yml +37 -0
  115. data/spec/cassettes/RedditKit_Client_Subreddits/_search_subreddits_by_name/returns_subreddit_names.yml +875 -0
  116. data/spec/cassettes/RedditKit_Client_Subreddits/_subreddit/returns_a_specified_subreddit.yml +100 -0
  117. data/spec/cassettes/RedditKit_Client_Subreddits/_subreddits/returns_a_specified_number_of_subreddits.yml +505 -0
  118. data/spec/cassettes/RedditKit_Client_Subreddits/_subreddits/returns_subreddits_from_a_specific_category.yml +510 -0
  119. data/spec/cassettes/RedditKit_Client_Subreddits/_subreddits_by_topic/returns_subreddit_names.yml +41 -0
  120. data/spec/cassettes/RedditKit_Client_Subreddits/_subscribe/requests_the_correct_resource.yml +46 -0
  121. data/spec/cassettes/RedditKit_Client_Subreddits/_subscribed_subreddits/returns_a_specified_number_of_subreddits.yml +415 -0
  122. data/spec/cassettes/RedditKit_Client_Subreddits/_subscribed_subreddits/returns_subreddits_from_a_specific_category.yml +58 -0
  123. data/spec/cassettes/RedditKit_Client_Subreddits/_subscribed_subreddits/returns_the_user_s_subscribed_subreddits.yml +3469 -0
  124. data/spec/cassettes/RedditKit_Client_Subreddits/_unsubscribe/requests_the_correct_resource.yml +46 -0
  125. data/spec/cassettes/RedditKit_Client_Users/_friends/returns_the_user_s_friends.yml +48 -0
  126. data/spec/cassettes/RedditKit_Client_Users/_my_content/returns_the_user_s_content.yml +60 -0
  127. data/spec/cassettes/RedditKit_Client_Users/_user/requests_the_correct_resource.yml +48 -0
  128. data/spec/cassettes/RedditKit_Client_Users/_user/returns_a_specified_user.yml +48 -0
  129. data/spec/cassettes/RedditKit_Client_Users/_user/returns_the_authenticated_user.yml +48 -0
  130. data/spec/cassettes/RedditKit_Client_Users/_user_content/returns_the_user_s_content.yml +41 -0
  131. data/spec/cassettes/RedditKit_Client_Users/_username_available_/returns_false_for_an_unavailable_username.yml +36 -0
  132. data/spec/cassettes/RedditKit_Client_Users/_username_available_/returns_true_for_an_available_username.yml +36 -0
  133. data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_comment_full_name_passed/downvotes_the_comment.yml +100 -0
  134. data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_comment_passed/downvotes_the_comment.yml +154 -0
  135. data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_link_full_name_passed/downvotes_the_link.yml +106 -0
  136. data/spec/cassettes/RedditKit_Client_Voting/_downvote/with_a_link_passed/downvotes_the_link.yml +166 -0
  137. data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_comment_full_name_passed/upvotes_the_comment.yml +100 -0
  138. data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_comment_passed/upvotes_the_comment.yml +154 -0
  139. data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_link_full_name_passed/upvotes_the_link.yml +106 -0
  140. data/spec/cassettes/RedditKit_Client_Voting/_upvote/with_a_link_passed/upvotes_the_link.yml +166 -0
  141. data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_comment_full_name_passed/withdraws_the_vote_on_the_comment.yml +154 -0
  142. data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_comment_passed/withdraws_the_vote_on_the_comment.yml +208 -0
  143. data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_link_full_name_passed/withdraws_the_vote_on_the_link.yml +166 -0
  144. data/spec/cassettes/RedditKit_Client_Voting/_withdraw_vote/with_a_link_passed/withdraws_the_vote_on_the_link.yml +226 -0
  145. data/spec/cassettes/RedditKit_Client_Wiki/_add_wiki_editor/requests_the_correct_resource.yml +46 -0
  146. data/spec/cassettes/RedditKit_Client_Wiki/_edit_wiki_page/requests_the_correct_resource.yml +48 -0
  147. data/spec/cassettes/RedditKit_Client_Wiki/_hide_wiki_revision/requests_the_correct_resource.yml +46 -0
  148. data/spec/cassettes/RedditKit_Client_Wiki/_remove_wiki_editor/requests_the_correct_resource.yml +46 -0
  149. data/spec/cassettes/RedditKit_Client_Wiki/_revert_to_revision/requests_the_correct_resource.yml +46 -0
  150. data/spec/cassettes/RedditKit_Comment/should_not_be_deleted_if_neither_author_and_comment_attributes_are_set_to_deleted_.yml +90 -0
  151. data/spec/cassettes/RedditKit_Comment/should_return_replies.yml +90 -0
  152. data/spec/cassettes/authenticated_client.yml +87 -0
  153. data/spec/redditkit/base_spec.rb +45 -0
  154. data/spec/redditkit/client/account_spec.rb +50 -0
  155. data/spec/redditkit/client/apps_spec.rb +58 -0
  156. data/spec/redditkit/client/captcha_spec.rb +30 -0
  157. data/spec/redditkit/client/comments_spec.rb +40 -0
  158. data/spec/redditkit/client/flair_spec.rb +92 -0
  159. data/spec/redditkit/client/links_spec.rb +103 -0
  160. data/spec/redditkit/client/miscellaneous_spec.rb +40 -0
  161. data/spec/redditkit/client/moderation_spec.rb +141 -0
  162. data/spec/redditkit/client/multireddits_spec.rb +158 -0
  163. data/spec/redditkit/client/private_messages_spec.rb +51 -0
  164. data/spec/redditkit/client/search_spec.rb +25 -0
  165. data/spec/redditkit/client/subreddits_spec.rb +83 -0
  166. data/spec/redditkit/client/users_spec.rb +92 -0
  167. data/spec/redditkit/client/voting_spec.rb +99 -0
  168. data/spec/redditkit/client/wiki_spec.rb +40 -0
  169. data/spec/redditkit/client_spec.rb +46 -0
  170. data/spec/redditkit/comment_spec.rb +26 -0
  171. data/spec/redditkit/creatable_spec.rb +24 -0
  172. data/spec/redditkit/error_spec.rb +61 -0
  173. data/spec/redditkit/link_spec.rb +33 -0
  174. data/spec/redditkit/multireddit_spec.rb +27 -0
  175. data/spec/redditkit/paginated_response_spec.rb +23 -0
  176. data/spec/redditkit/thing_spec.rb +18 -0
  177. data/spec/redditkit/votable_spec.rb +52 -0
  178. data/spec/redditkit_spec.rb +21 -0
  179. data/spec/spec_helper.rb +124 -0
  180. metadata +390 -0
@@ -0,0 +1,25 @@
1
+ module RedditKit
2
+ class Client
3
+
4
+ # Methods for searching reddit's links.
5
+ module Search
6
+
7
+ # Search for links.
8
+ #
9
+ # @param query [String] The search query.
10
+ # @option options [true, false] :restrict_to_subreddit Whether to search only in a specified subreddit.
11
+ # @option options [String, RedditKit::Subreddit] :subreddit The optional subreddit to search.
12
+ # @option options [1..100] limit The number of links to return.
13
+ # @option options [String] before Only return links before this full name.
14
+ # @option options [String] after Only return links after this full name.
15
+ # @return [RedditKit::PaginatedResponse]
16
+ def search(query, options = {})
17
+ path = "%s/search.json" % ('r/' + options[:subreddit] if options[:subreddit])
18
+ parameters = { :q => query, :restrict_sr => options[:restrict_to_subreddit], :limit => options[:limit] }
19
+
20
+ objects_from_response(:get, path, parameters)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,120 @@
1
+ require 'redditkit/subreddit'
2
+
3
+ module RedditKit
4
+ class Client
5
+
6
+ # Methods for interacting with subreddits.
7
+ module Subreddits
8
+
9
+ # Gets subreddits from a specified category.
10
+ #
11
+ # @option options [new, popular, banned] category The category of subreddits. Defaults to popular.
12
+ # @option options [1..100] limit The number of subreddits to return.
13
+ # @option options [String] before Only return subreddits before this id.
14
+ # @option options [String] after Only return subreddits after this id.
15
+ # @return [RedditKit::PaginatedResponse]
16
+ def subreddits(options = {})
17
+ category = options[:category] or 'popular'
18
+ path = "reddits/#{category}.json"
19
+ options.delete :category
20
+
21
+ objects_from_response(:get, path, options)
22
+ end
23
+
24
+ # Gets the current user's subscribed subreddits.
25
+ #
26
+ # @option options [subscriber, contributor, moderator] category The category from which to return subreddits. Defaults to subscriber.
27
+ # @option options [1..100] limit The number of subreddits to return.
28
+ # @option options [String] before Only return subreddits before this id.
29
+ # @option options [String] after Only return subreddits after this id.
30
+ # @return [RedditKit::PaginatedResponse]
31
+ def subscribed_subreddits(options = {})
32
+ category = options[:category] or 'subscriber'
33
+ path = "subreddits/mine/#{category}.json"
34
+ options.delete :category
35
+
36
+ objects_from_response(:get, path, options)
37
+ end
38
+
39
+ # Gets a subreddit object.
40
+ #
41
+ # @param subreddit_name [String] A subreddit's display name.
42
+ # @return [RedditKit::Subreddit]
43
+ # @example client.subreddit "programming"
44
+ def subreddit(subreddit_name)
45
+ object_from_response(:get, "r/#{subreddit_name}/about.json", nil)
46
+ end
47
+
48
+ # Subscribes to a subreddit.
49
+ #
50
+ # @param subreddit [String, RedditKit::Subreddit] A subreddit's full name, or a RedditKit::Subreddit.
51
+ def subscribe(subreddit)
52
+ full_name = extract_full_name subreddit
53
+ parameters = { :action => 'sub', :sr => full_name }
54
+
55
+ post("api/subscribe", parameters)
56
+ end
57
+
58
+ # Unsubscribes from a subreddit.
59
+ #
60
+ # @param subreddit [String, RedditKit::Subreddit] A subreddit's full name, or a RedditKit::Subreddit.
61
+ def unsubscribe(subreddit)
62
+ full_name = extract_full_name subreddit
63
+ parameters = { :action => 'unsub', :sr => full_name }
64
+
65
+ post("api/subscribe", parameters)
66
+ end
67
+
68
+ # Gets a random subreddit.
69
+ #
70
+ # @return [RedditKit::Subreddit]
71
+ def random_subreddit
72
+ response = get('r/random', nil)
73
+ headers = response[:response_headers]
74
+ location = headers[:location]
75
+
76
+ subreddit_name = location[/\/r\/(.*)\//, 1]
77
+ subreddit subreddit_name
78
+ end
79
+
80
+ # Searches for subreddits with a specific name.
81
+ #
82
+ # @param name [String] The name to search for.
83
+ # @return [RedditKit::PaginatedResponse]
84
+ def search_subreddits_by_name(name)
85
+ parameters = { :q => name }
86
+ objects_from_response :get, 'subreddits/search.json', parameters
87
+ end
88
+
89
+ # Gets an array of subreddit names by topic.
90
+ #
91
+ # @param topic [String] The desired topic.
92
+ # @return [Array<String>] An array of subreddit names.
93
+ # @example RedditKit.subreddits_by_topic 'programming'
94
+ def subreddits_by_topic(topic)
95
+ parameters = { :query => topic }
96
+
97
+ response = get('api/subreddits_by_topic.json', parameters)
98
+ body = response[:body]
99
+
100
+ body.collect { |subreddit| subreddit[:name] }
101
+ end
102
+
103
+ # Gets an array of recommended subreddits.
104
+ #
105
+ # @param subreddits [Array<String>] An array of subreddit names.
106
+ # @return [Array<String>] An array of recommended subreddit names.
107
+ # @example RedditKit.recommended_subreddits %w(ruby programming)
108
+ def recommended_subreddits(subreddits)
109
+ names = subreddits.join(',')
110
+ parameters = { :srnames => names }
111
+
112
+ response = get('api/subreddit_recommendations.json', parameters)
113
+ body = response[:body]
114
+
115
+ body.collect { |subreddit| subreddit[:sr_name] }
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,109 @@
1
+ require 'redditkit/user'
2
+
3
+ module RedditKit
4
+ class Client
5
+
6
+ # Methods for interacting with reddit users.
7
+ module Users
8
+
9
+ # Gets a user object.
10
+ #
11
+ # @param username [String] A reddit account's username. Gets the current user if this is nil.
12
+ # @return [RedditKit::User]
13
+ # @example current_user = client.user
14
+ # @example user = client.user 'amberlynns'
15
+ def user(username = nil)
16
+ if username
17
+ object_from_response(:get, "user/#{username}/about.json", nil)
18
+ else
19
+ object_from_response(:get, "api/me.json", nil)
20
+ end
21
+ end
22
+
23
+ # Gets links and comments for the current user.
24
+ #
25
+ # @option options [overview, comments, submitted, liked, disliked] :category The category from which to return links and comments. Defaults to overview.
26
+ # @option options [1..100] :limit The number of links and comments to return.
27
+ # @option options [String] :before Only return links and comments before this id.
28
+ # @option options [String] :after Only return links and comments after this id.
29
+ # @return [RedditKit::PaginatedResponse]
30
+ def my_content(options = {})
31
+ category = options[:category] || :overview
32
+ path = "user/#{@username}/#{category}.json"
33
+ options.delete :category
34
+
35
+ objects_from_response(:get, path, options)
36
+ end
37
+
38
+ # Gets links and comments for a user.
39
+ #
40
+ # @option options [overview, comments, submitted, liked, disliked] :category The category from which to return links and comments. Defaults to overview.
41
+ # @option options [1..100] :limit The number of links and comments to return.
42
+ # @option options [String] :before Only return links and comments before this id.
43
+ # @option options [String] :after Only return links and comments after this id.
44
+ # @return [RedditKit::PaginatedResponse]
45
+ # @note Public access to the liked and disliked categories is disabled by default, so this will return an empty array for most users.
46
+ def user_content(user, options = {})
47
+ username = user
48
+
49
+ path = "user/#{username}/%s.json" % (options[:category] if options[:category])
50
+ options.delete :category
51
+
52
+ objects_from_response(:get, path, options)
53
+ end
54
+
55
+ # Gets the current user's friends.
56
+ #
57
+ # @return [Array<OpenStruct>]
58
+ def friends
59
+ response = request(:get, 'prefs/friends.json', nil, https_connection)
60
+ body = response[:body]
61
+ friends = body[0][:data][:children]
62
+
63
+ friends.collect { |friend| OpenStruct.new(friend) }
64
+ end
65
+
66
+ # Adds a user to the current user's friend list.
67
+ #
68
+ # @param user [String, RedditKit::User] A user's username, or a RedditKit::User.
69
+ def friend(user)
70
+ friend_name = extract_string(user, :username)
71
+ friend_request 'friend', :container => current_user.full_name, :name => friend_name, :type => :friend
72
+ end
73
+
74
+ # Removes a user from the current user's friend list.
75
+ #
76
+ # @param user [String, RedditKit::User] A user's ID, or a RedditKit::User.
77
+ def unfriend(user)
78
+ friend_name = extract_string(user, :username)
79
+ friend_request 'unfriend', :container => current_user.full_name, :name => friend_name, :type => :friend
80
+ end
81
+
82
+ # Checks whether a specific username is available.
83
+ #
84
+ # @param username [String] A username for which to check availability.
85
+ # @return [Boolean]
86
+ # @example puts "Username is available" if client.username_available? 'some_username'
87
+ def username_available?(username)
88
+ response = get('api/username_available.json', :user => username)
89
+ available = response[:body]
90
+
91
+ available == 'true'
92
+ end
93
+
94
+ # Registers a new reddit account.
95
+ #
96
+ # @option options [String] username The username to register.
97
+ # @option options [String] password The password for the account.
98
+ # @option options [String] email The optional email address for the account.
99
+ # @option options [String] captcha_identifier The identifier for the CAPTCHA challenge solved by the user.
100
+ # @option options [String] captcha The user's response to the CAPTCHA challenge.
101
+ # @option options [Boolean] remember Whether to keep the user's session cookie beyond the current session.
102
+ def register(username, password, options = {})
103
+ parameters = { :user => username, :passwd => password, :passwd2 => password, :captcha => options[:captcha], :iden => options[:captcha_identifier] }
104
+ post('api/register', parameters)
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,137 @@
1
+ require 'redditkit/paginated_response'
2
+
3
+ module RedditKit
4
+ class Client
5
+
6
+ # Methods for streamlining requests to reddit's servers.
7
+ module Utilities
8
+
9
+ private
10
+
11
+ # Return an id from a string or a RedditKit::Thing object.
12
+ #
13
+ # @param object [String, RedditKit::Thing] A string or object.
14
+ # @return [String]
15
+ def extract_id(object)
16
+ extract_string object, :id
17
+ end
18
+
19
+ # Return a full name from a string or a RedditKit::Thing object.
20
+ #
21
+ # @param object [String, RedditKit::Thing] A string or object.
22
+ # @return [String]
23
+ def extract_full_name(object)
24
+ extract_string object, :full_name
25
+ end
26
+
27
+ def extract_string(object, attribute_name)
28
+ case object
29
+ when ::String
30
+ object
31
+ else
32
+ object.send attribute_name if object.respond_to? attribute_name
33
+ end
34
+ end
35
+
36
+ # Return the class of an object from a response.
37
+ #
38
+ # @param response [Faraday::Response] A response.
39
+ # @return [Class]
40
+ def object_class_from_response(response)
41
+ kind = object_kind_from_response(response)
42
+ object_class_from_kind(kind)
43
+ end
44
+
45
+ # Return the class of an object of a given kind.
46
+ #
47
+ # @param kind [String] The object's kind.
48
+ # @return [Class]
49
+ def object_class_from_kind(kind)
50
+ case kind
51
+ when "t1"
52
+ RedditKit::Comment
53
+ when "t2"
54
+ RedditKit::User
55
+ when "t3"
56
+ RedditKit::Link
57
+ when "t4"
58
+ RedditKit::PrivateMessage
59
+ when "t5"
60
+ RedditKit::Subreddit
61
+ when "LabeledMulti"
62
+ RedditKit::Multireddit
63
+ when "LabeledMultiDescription"
64
+ RedditKit::MultiredditDescription
65
+ when "modaction"
66
+ RedditKit::ModeratorAction
67
+ end
68
+ end
69
+
70
+ def object_kind_from_response(response)
71
+ response[:kind]
72
+ end
73
+
74
+ def object_from_response(request_type, path, parameters = {})
75
+ response = send(request_type.to_sym, path, parameters)
76
+ body = response[:body]
77
+
78
+ object_class = object_class_from_response(body)
79
+ object_class.new(body) if object_class
80
+ end
81
+
82
+ def objects_from_response(request_type, path, parameters = {})
83
+ response = send(request_type.to_sym, path, parameters)
84
+ body = response[:body]
85
+
86
+ if body.is_a?(Hash) and body[:kind] == 'Listing'
87
+ data = body[:data]
88
+ results = objects_from_listing(body)
89
+
90
+ RedditKit::PaginatedResponse.new(data[:before], data[:after], results)
91
+ elsif body.is_a?(Array)
92
+ objects_from_array body
93
+ elsif body.is_a?(Hash)
94
+ objects_from_array body[:data]
95
+ end
96
+ end
97
+
98
+ def objects_from_listing(listing)
99
+ children = listing[:data][:children]
100
+ objects_from_array children
101
+ end
102
+
103
+ def objects_from_array(array)
104
+ array.map do |thing|
105
+ object_class = object_class_from_response(thing)
106
+ object_class.new(thing) if object_class
107
+ end
108
+ end
109
+
110
+ def comments_from_response(request_type, path, parameters = {})
111
+ response = send(request_type.to_sym, path, parameters)
112
+ body = response[:body]
113
+ comments_listing = body.last
114
+
115
+ objects_from_listing(comments_listing)
116
+ end
117
+
118
+ def path_for_multireddit(username, multireddit_name)
119
+ "/user/#{username}/m/#{multireddit_name}"
120
+ end
121
+
122
+ # Performs a friend or unfriend request.
123
+ #
124
+ # @param type [friend, unfriend] The type of request.
125
+ # @param options Any parameters to send with the request.
126
+ def friend_request(type, options)
127
+ if options[:subreddit]
128
+ options[:r] = options[:subreddit]
129
+ options.delete :subreddit
130
+ end
131
+
132
+ post("api/#{type}", options)
133
+ end
134
+
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,41 @@
1
+ module RedditKit
2
+ class Client
3
+
4
+ # Methods for voting on links and comments.
5
+ module Voting
6
+
7
+ # Upvotes a link or comment.
8
+ #
9
+ # @param link_or_comment [String, RedditKit::Comment, RedditKit::Link] The link or comment to upvote.
10
+ def upvote(link_or_comment)
11
+ vote link_or_comment, 1
12
+ end
13
+
14
+ # Downvotes a link or comment.
15
+ #
16
+ # @param link_or_comment [String, RedditKit::Comment, RedditKit::Link] The link or comment to downvote.
17
+ def downvote(link_or_comment)
18
+ vote link_or_comment, -1
19
+ end
20
+
21
+ # Withdraws a vote on a link or comment.
22
+ #
23
+ # @param link_or_comment [String, RedditKit::Comment, RedditKit::Link] The link or comment from which to withdraw the vote.
24
+ def withdraw_vote(link_or_comment)
25
+ vote link_or_comment, 0
26
+ end
27
+
28
+ # Votes on a link or comment.
29
+ #
30
+ # @param link_or_comment [String, RedditKit::Comment, RedditKit::Link] The link or comment from which to withdraw the vote.
31
+ # @param direction [-1, 0, 1] Downvote, no vote, and upvote respectively.
32
+ def vote(link_or_comment, direction)
33
+ full_name = extract_full_name(link_or_comment)
34
+ parameters = { :id => full_name, :dir => direction, :api_type => 'json' }
35
+
36
+ post('api/vote', parameters)
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,83 @@
1
+ module RedditKit
2
+ class Client
3
+
4
+ # Methods for interacting with a subreddit's wiki.
5
+ module Wiki
6
+
7
+ # Adds a user as an approved editor of a wiki page.
8
+ #
9
+ # @param subreddit [String, RedditKit::Subreddit] A subreddit's display name, or a RedditKit::Subreddit.
10
+ # @param user [String, RedditKit::User] A user's full name, or a RedditKit::User.
11
+ # @param page [String] page The name of an existing wiki page.
12
+ def add_wiki_editor(subreddit, user, page)
13
+ toggle_wiki_editor(subreddit, user, page, 'add')
14
+ end
15
+
16
+ # Removes a user from being an approved editor of a wiki page.
17
+ #
18
+ # @param subreddit [String, RedditKit::Subreddit] A subreddit's display name, or a RedditKit::Subreddit.
19
+ # @param user [String, RedditKit::User] A user's full name, or a RedditKit::User.
20
+ # @param page [String] page The name of an existing wiki page.
21
+ def remove_wiki_editor(subreddit, user, page)
22
+ toggle_wiki_editor(subreddit, user, page, 'del')
23
+ end
24
+
25
+ # Edits a wiki page.
26
+ #
27
+ # @option options [String, RedditKit::Subreddit] subreddit A subreddit's display name, or a RedditKit::Subreddit.
28
+ # @option options [String] page The name of an existing wiki page.
29
+ # @option options [String] content The contents of the edit.
30
+ # @option options [String] reason The reason for the edit.
31
+ # @option options [String] previous_revision The starting revision for this edit.
32
+ def edit_wiki_page(options)
33
+ subreddit_name = extract_string(options[:subreddit], :display_name)
34
+ parameters = { :page => options[:page], :previous => options[:previous_revision], :content => options[:content], :reason => options[:reason] }
35
+
36
+ post("r/#{subreddit_name}/api/wiki/edit", parameters)
37
+ end
38
+
39
+ # Hides a wiki page revision. If the revision is already hidden, this will unhide it.
40
+ #
41
+ # @option options [String, RedditKit::Subreddit] subreddit A subreddit's display name, or a RedditKit::Subreddit.
42
+ # @option options [String] page The name of an existing wiki page.
43
+ # @option options [String] revision The revision to hide.
44
+ # @return [Boolean] True if the revision is now hidden, false if it is not hidden.
45
+ def hide_wiki_revision(options)
46
+ subreddit_name = extract_string(options[:subreddit], :display_name)
47
+ options.delete :subreddit
48
+
49
+ response = post("r/#{subreddit_name}/api/wiki/hide", options)
50
+ response[:body][:status]
51
+ end
52
+
53
+ # Reverts to a specific wiki page revision.
54
+ #
55
+ # @option options [String, RedditKit::Subreddit] subreddit A subreddit's display name, or a RedditKit::Subreddit.
56
+ # @option options [String] page The name of an existing wiki page.
57
+ # @option options [String] revision The revision to revert to.
58
+ def revert_to_revision(options)
59
+ subreddit_name = extract_string(options[:subreddit], :display_name)
60
+ options.delete :subreddit
61
+
62
+ post("r/#{subreddit_name}/api/wiki/revert", options)
63
+ end
64
+
65
+ private
66
+
67
+ # Adds or removes a user as an approved editor of a wiki page.
68
+ #
69
+ # @param subreddit [String, RedditKit::Subreddit] A subreddit's display name, or a RedditKit::Subreddit.
70
+ # @param user [String, RedditKit::User] A user's full name, or a RedditKit::User.
71
+ # @param page [String] page The name of an existing wiki page.
72
+ # @param status [add, del] Whether to add or delete a user.
73
+ def toggle_wiki_editor(subreddit, user, page, status)
74
+ subreddit_name = extract_string(subreddit, :display_name)
75
+ username = extract_string(user, :username)
76
+ parameters = { :page => page, :username => username }
77
+
78
+ post("r/#{subreddit_name}/api/wiki/alloweditor/#{status}", parameters)
79
+ end
80
+
81
+ end
82
+ end
83
+ end