1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
#![deny(missing_docs)] //! # rawr - Rust API Wrapper for Reddit //! This crate provides simple yet powerful access to the Reddit API. //! ## Quick Start //! This section will teach you the basics of `rawr`, so you can get started with your project //! easily. //! ### Creating a Client //! To create a client to access the Reddit API, you can use the `RedditClient` class. All you need //! to do is pass in the user agent when creating the client to have anonymous access. In order //! to post or reply, you need to log in (which will be explained soon!). //! //! As well as passing in a user agent, you need to pass in an *authenticator*, which handles //! logging in and proving who you are to Reddit. For now, we'll log in anonymously with //! `AnonymousAuthenticator`. You'll definitely want to take a look at the //! [auth](./auth/index.html) module documentation to find out how to log in to an account. //! //! ```rust,no_run //! use rawr::client::RedditClient; //! use rawr::auth::AnonymousAuthenticator; //! let client = RedditClient::new("my user agent", AnonymousAuthenticator::new()); //! ``` //! //! It is important that you pick a good user agent. The ideal format is //! `platform:program:version (by /u/yourname)`, e.g. `linux:rawr:v0.0.1 (by /u/Aurora0001)`. //! //! ### Getting a List of Posts //! First, you'll need to select the subreddit that you want to get a listing from. For our //! example, we'll use /r/all. To get that subreddit, we can do this: //! //! ```rust,no_run //! # use rawr::client::RedditClient; //! # use rawr::auth::AnonymousAuthenticator; //! let client = RedditClient::new("?:rawr:doc-tests", AnonymousAuthenticator::new()); //! let all = client.subreddit("all"); //! ``` //! //! Once we have the subreddit object, we can get the post list. There are several listing types //! provided by Reddit: //! - Hot - the default sort, which shows the 'best' posts at this moment. //! - New - posts ordered from newest to oldest. //! - Rising - posts gaining in popularity (usually, this is quite a short listing and only has //! 10-20 items) //! //! There are also 'time-scoped' listings that require a timespan as well. This is essentially //! the same as the 'links from: all time' dropdown. //! - Controversial - posts that have received lots of upvotes and downvotes. //! - Top - posts that have the highest score overall. //! //! Here's an example of using the `hot` listing: //! //! ```rust,no_run //! # use rawr::client::RedditClient; //! # use rawr::auth::AnonymousAuthenticator; //! use rawr::options::ListingOptions; //! # let client = RedditClient::new("?:rawr:doc-tests", AnonymousAuthenticator::new()); //! # let all = client.subreddit("all"); //! let listing = all.hot(ListingOptions::default()).expect("Request unsuccessful"); //! ``` //! //! *Why do I need the `expect` call?* Since it is possible for a request to the API to fail, //! most of the API wrapper returns `Result<_, APIError>` where `_` is the actual value from the //! API. This allows you to handle the error gracefully if you want, but for our examples //! we will always use `expect` to simplify the examples. //! //! The `ListingOptions` object is used to configure various options such as the amount of posts //! to fetch in each request and the anchor. For more information, see the documentation for //! `ListingOptions`. //! //! ### Using the Post Listing //! The `Listing` objects implement `Iterator`, which means it's really convenient to loop through //! multiple posts. You can just use a for loop, like this: //! //! ```rust,no_run //! # use rawr::client::RedditClient; //! # use rawr::auth::AnonymousAuthenticator; //! # use rawr::options::ListingOptions; //! # let client = RedditClient::new("?:rawr:doc-tests", AnonymousAuthenticator::new()); //! # let all = client.subreddit("all"); //! let listing = all.hot(ListingOptions::default()).expect("Could not fetch posts"); //! for post in listing { //! println!("{}", post.title()); //! } //! ``` //! ### Getting Replies //! If you're interested in the replies to a post, you can get them using the `replies()` method. //! `replies()` returns a `CommentList`, which acts a lot like a `Listing` in that it will //! automatically fetch more comments as needed. However, unlike post listings, the comments //! section is threaded, so you can get the `replies()` to a comment as well. //! //! Here's how to get the first comment (if available) for every post in the /r/all/hot //! listing: //! //! ```rust,no_run //! # use rawr::auth::AnonymousAuthenticator; //! # use rawr::client::RedditClient; //! # use rawr::options::ListingOptions; //! use rawr::traits::{Commentable, Content}; //! # let client = RedditClient::new("rawr", AnonymousAuthenticator::new()); //! let all = client.subreddit("all"); //! for post in all.hot(ListingOptions::default()).expect("Request failed") { //! if let Some(comment) = post.replies().expect("Could not get replies").next() { //! println!("{}", comment.author().name); //! } //! } //! ``` //! //! *'What were those traits about?'*, I hear you say. The `Commentable` trait provides //! functions to work with comments and manipulate them. The `Commentable` trait is implemented //! in both the `Comment` struct and the `Submission` struct, because you can comment on either. //! This also explains why you can get the `replies()` for a `Comment` using the same interface. //! //! The `Content` trait is a little bit different. Things that implement `Content` were created by //! a user and exist in a subreddit (so they're either submissions or comments). You can use this //! trait to delete posts, get the author or get the parent subreddit. //! //! ### Replying //! The `Commentable` trait also allows your client to reply to anything that implements it. //! You can reply like this: //! //! ```rust,no_run //! # use rawr::auth::AnonymousAuthenticator; //! # use rawr::client::RedditClient; //! # use rawr::options::ListingOptions; //! # use rawr::traits::{Commentable, Content}; //! # let client = RedditClient::new("rawr", AnonymousAuthenticator::new()); //! let all = client.subreddit("all"); //! let mut listing = all.hot(ListingOptions::default()).expect("Request failed"); //! if let Some(top_post) = listing.next() { //! top_post.reply("This is cool... I think. I'm a bot.").expect("Posting failed!"); //! } //! ``` //! //! Most actions in the API return a `Result` so you can handle any errors that occur. In this //! example, we just use `expect()`, but real code should handle this more gracefully, otherwise //! the code may panic. Be prepared to accept HTTP 5xx errors if reddit is having trouble with //! their servers; this will be returned to you as a `APIError::HTTPError` with the error //! status in the enum variant. //! ### Posting a Thread //! Reddit has two types of submissions: link posts and self posts. Link posts are hyperlinked //! to their URL, but have no body text. Self posts have a body but don't link anywhere. Both //! earn karma. //! //! To post a link post, you can use the `submit_link()` method. First, you need to create a //! `LinkPost` object that can configure your post, like this: //! //! ``` //! use rawr::options::LinkPost; //! let post = LinkPost::new("title", "https://example.com"); //! ``` //! //! If that link has been posted previously in the subreddit, you need to mark it as a repost, like //! this: //! //! ``` //! # use rawr::options::LinkPost; //! let post = LinkPost::new("title", "https://example.com").resubmit(); //! ``` //! //! You can then submit it, like this: //! //! ```rust,no_run //! # use rawr::auth::AnonymousAuthenticator; //! # use rawr::client::RedditClient; //! # use rawr::options::ListingOptions; //! # use rawr::traits::{Commentable, Content}; //! use rawr::options::LinkPost; //! # let client = RedditClient::new("rawr", AnonymousAuthenticator::new()); //! let programming = client.subreddit("programming"); //! let post = LinkPost::new("I love Rust!", "https://rust-lang.org"); //! programming.submit_link(post).expect("Could not submit link!"); //! ``` //! //! Submitting a self post is largely the same, but the `resubmit` function is not available //! on the `SelfPost` struct. Example: //! //! ```rust,no_run //! # use rawr::auth::AnonymousAuthenticator; //! # use rawr::client::RedditClient; //! # use rawr::options::ListingOptions; //! # use rawr::traits::{Commentable, Content}; //! use rawr::options::SelfPost; //! # let client = RedditClient::new("rawr", AnonymousAuthenticator::new()); //! let programming = client.subreddit("programming"); //! let post = SelfPost::new("I love Rust!", "It's great! **Wow**!"); //! programming.submit_text(post).expect("Could not submit link!"); //! ``` //! //! # More Advanced Features //! `rawr` also supports: //! - Getting a user by name (see `RedditClient.user("name")`) //! - Setting user flairs (see the `user` module) //! - Setting post flairs (see `Submission.flair`) //! - Getting 'about' information (see `Subreddit.about()`) //! //! # Not Yet Implemented //! - Multireddits //! - Live Threads //! //! Want to help? Take a look at the issue tracker! extern crate serde; extern crate serde_json; extern crate hyper; pub mod auth; pub mod client; /// Deserialized API responses. pub mod responses; /// Traits for common API functionality. pub mod traits; /// Error types used to signal problems with requests. pub mod errors; /// Reddit structures such as submissions, comments and subreddits. pub mod structures; /// Configuration options for API requests. pub mod options; /// Basic `rawr` structures to import with `use rawr::prelude::*`; pub mod prelude; #[cfg(test)] mod tests { use client::RedditClient; use structures::submission::Submission; use options::ListingOptions; use auth::AnonymousAuthenticator; #[test] fn hot_length() { let client = RedditClient::new("rawr", AnonymousAuthenticator::new()); let r_all = client.subreddit("all"); let hot = r_all.hot(ListingOptions::default()).expect("Request failed!"); let hot_list = hot.take(26).collect::<Vec<Submission>>(); assert_eq!(hot_list.len() as usize, 26); } }