diff --git a/src/apps.rs b/src/apps.rs index b0bccd2..56fa321 100644 --- a/src/apps.rs +++ b/src/apps.rs @@ -1,3 +1,5 @@ +use std::fmt; + /// Builder struct for defining your application. /// ``` /// let app = AppBuilder { @@ -9,16 +11,24 @@ /// ``` #[derive(Debug, Default, Serialize)] pub struct AppBuilder<'a> { + /// Name of the application. Will be displayed when the user is deciding to + /// grant permission. pub client_name: &'a str, + /// Where the user should be redirected after authorization + /// (for no redirect, use `urn:ietf:wg:oauth:2.0:oob`) pub redirect_uris: &'a str, + /// Permission scope of the application. pub scopes: Scope, + /// URL to the homepage of your application. #[serde(skip_serializing_if="Option::is_none")] pub website: Option<&'a str>, } +/// Permission scope of the application. +/// [Details on what each permission provides](//github.com/tootsuite/documentation/blob/master/Using-the-API/OAuth-details.md) #[derive(Debug, Clone, Copy, Serialize)] pub enum Scope { - /// All Permissions, equiavlent to `read write follow` + /// All Permissions, equivalent to `read write follow` #[serde(rename = "read write follow")] All, /// Only permission to add and remove followers. @@ -27,18 +37,22 @@ pub enum Scope { /// Read only permissions. #[serde(rename = "read")] Read, + /// Read & Follow permissions. #[serde(rename = "read follow")] ReadFollow, + /// Read & Write permissions. #[serde(rename = "read write")] ReadWrite, + /// Write only permissions. #[serde(rename = "write")] Write, + /// Write & Follow permissions. #[serde(rename = "write follow")] WriteFollow, } -impl ::std::fmt::Display for Scope { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +impl fmt::Display for Scope { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Scope::*; write!(f, "{}", match *self { All => "read write follow", diff --git a/src/entities/account.rs b/src/entities/account.rs index 451c92b..bcb7ca8 100644 --- a/src/entities/account.rs +++ b/src/entities/account.rs @@ -1,19 +1,39 @@ +//! A module containing everything relating to a account returned from the api. + use chrono::prelude::*; + +/// A struct representing an Account. #[derive(Debug, Clone, Deserialize)] pub struct Account { - pub id: u64, - pub username: String, + /// Equals `username` for local users, includes `@domain` for remote ones. pub acct: String, - pub display_name: String, - pub note: String, - pub url: String, + /// URL to the avatar image pub avatar: String, + /// URL to the avatar static image (gif) pub avatar_static: String, - pub header: String, - pub header_static: String, - pub locked: bool, + /// The time the account was created. pub created_at: DateTime, + /// The account's display name. + pub display_name: String, + /// The number of followers for the account. pub followers_count: u64, + /// The number of accounts the given account is following. pub following_count: u64, + /// URL to the header image. + pub header: String, + /// URL to the header static image (gif). + pub header_static: String, + /// The ID of the account. + pub id: u64, + /// Boolean for when the account cannot be followed without waiting for + /// approval first. + pub locked: bool, + /// Biography of user. + pub note: String, + /// The number of statuses the account has made. pub statuses_count: u64, + /// URL of the user's profile page (can be remote). + pub url: String, + /// The username of the account. + pub username: String, } diff --git a/src/entities/attachment.rs b/src/entities/attachment.rs index 5d67e13..788348a 100644 --- a/src/entities/attachment.rs +++ b/src/entities/attachment.rs @@ -1,39 +1,64 @@ +//! Module containing everything related to media attachements. + +/// A struct representing a media attachment. #[derive(Debug, Clone, Deserialize)] pub struct Attachment { + /// ID of the attachment. pub id: String, + /// The media type of an attachment. #[serde(rename="type")] pub media_type: MediaType, + /// URL of the locally hosted version of the image. pub url: String, + /// For remote images, the remote URL of the original image. pub remote_url: Option, + /// URL of the preview image. pub preview_url: String, + /// Shorter URL for the image, for insertion into text + /// (only present on local images) pub text_url: Option, + /// Meta information about the attachment. pub meta: Option, + /// Noop will be removed. pub description: Option, } +/// Information about the attachment itself. #[derive(Debug, Deserialize, Clone)] pub struct Meta { + /// Original version. original: ImageDetails, + /// Smaller version. small: ImageDetails, } +/// Dimensions of an attachement. #[derive(Debug, Deserialize, Clone)] pub struct ImageDetails { + /// width of attachment. width: u64, + /// height of attachment. height: u64, + /// A string of `widthxheight`. size: String, + /// The aspect ratio of the attachment. aspect: f64, } +/// The type of media attachment. #[derive(Debug, Deserialize, Clone, Copy)] pub enum MediaType { + /// An image. #[serde(rename = "image")] Image, + /// A video file. #[serde(rename = "video")] Video, + /// A gifv format file. #[serde(rename = "gifv")] Gifv, + /// Unknown format. #[serde(rename = "unknown")] Unknown, } diff --git a/src/entities/card.rs b/src/entities/card.rs index b2a4e8b..babd43d 100644 --- a/src/entities/card.rs +++ b/src/entities/card.rs @@ -1,7 +1,14 @@ +//! Module representing cards of statuses. + +/// A card of a status. #[derive(Debug, Clone, Deserialize)] pub struct Card { + /// The url associated with the card. pub url: String, + /// The title of the card. pub title: String, + /// The card description. pub description: String, + /// The image associated with the card, if any. pub image: String, } diff --git a/src/entities/context.rs b/src/entities/context.rs index 518a02b..d79e3f7 100644 --- a/src/entities/context.rs +++ b/src/entities/context.rs @@ -1,7 +1,13 @@ +//! A module about contexts of statuses. + use super::status::Status; +/// A context of a status returning a list of statuses it replied to and +/// statuses replied to it. #[derive(Debug, Clone, Deserialize)] pub struct Context { + /// Statuses that were replied to. pub ancestors: Vec, + /// Statuses that replied to this status. pub descendants: Vec, } diff --git a/src/entities/instance.rs b/src/entities/instance.rs index 994e1ad..6100138 100644 --- a/src/entities/instance.rs +++ b/src/entities/instance.rs @@ -1,7 +1,15 @@ +//! Module containing everything related to an instance. + +/// A struct containing info of an instance. #[derive(Debug, Clone, Deserialize)] pub struct Instance { + /// URI of the current instance pub uri: String, + /// The instance's title. pub title: String, + /// A description for the instance. pub description: String, + /// An email address which can be used to contact the + /// instance administrator. pub email: String, } diff --git a/src/entities/mod.rs b/src/entities/mod.rs index d914d05..4cd65db 100644 --- a/src/entities/mod.rs +++ b/src/entities/mod.rs @@ -14,6 +14,8 @@ pub mod status; pub struct Empty {} pub mod prelude { + //! The purpose of this module is to alleviate imports of many common structs + //! by adding a glob import to the top of mastodon heavy modules: pub use super::Empty; pub use super::account::Account; pub use super::attachment::{Attachment, MediaType}; diff --git a/src/entities/notification.rs b/src/entities/notification.rs index 058bec0..f3fd08e 100644 --- a/src/entities/notification.rs +++ b/src/entities/notification.rs @@ -1,25 +1,38 @@ +//! Module containing all info about notifications. + use chrono::prelude::*; use super::account::Account; use super::status::Status; +/// A struct containing info about a notification. #[derive(Debug, Clone, Deserialize)] pub struct Notification { + /// The notification ID. pub id: u64, + /// The type of notification. #[serde(rename = "type")] pub notification_type: NotificationType, + /// The time the notification was created. pub created_at: DateTime, + /// The Account sending the notification to the user. pub account: Account, + /// The Status associated with the notification, if applicable. pub status: Option, } +/// The type of notification. #[derive(Debug, Clone, Deserialize)] pub enum NotificationType { + /// Someone mentioned the application client in another status. #[serde(rename = "mention")] Mention, + /// Someone reblogged one of the application client's statuses. #[serde(rename = "reblog")] Reblog, + /// Someone favourited one of the application client's statuses. #[serde(rename = "favourite")] Favourite, + /// Someone followed the application client. #[serde(rename = "follow")] Follow, } diff --git a/src/entities/relationship.rs b/src/entities/relationship.rs index cf3c7ed..120ab5f 100644 --- a/src/entities/relationship.rs +++ b/src/entities/relationship.rs @@ -1,8 +1,17 @@ +//! module containing everything relating to a relationship with +//! another account. + +/// A struct containing information about a relationship with another account. #[derive(Debug, Clone, Deserialize)] pub struct Relationship { + /// Whether the application client follows the account. pub following: bool, + /// Whether the account follows the application client. pub followed_by: bool, + /// Whether the application client blocks the account. pub blocking: bool, + /// Whether the application client blocks the account. pub muting: bool, + /// Whether the application client has requested to follow the account. pub requested: bool, } diff --git a/src/entities/report.rs b/src/entities/report.rs index b397a62..bba0e11 100644 --- a/src/entities/report.rs +++ b/src/entities/report.rs @@ -1,5 +1,10 @@ +//! module containing information about a finished report of a user. + +/// A struct containing info about a report. #[derive(Debug, Clone, Deserialize)] pub struct Report { + /// The ID of the report. pub id: u64, + /// The action taken in response to the report. pub action_taken: String, } diff --git a/src/entities/search_result.rs b/src/entities/search_result.rs index 2c75f36..d357488 100644 --- a/src/entities/search_result.rs +++ b/src/entities/search_result.rs @@ -1,8 +1,14 @@ +//! A module containing info relating to a search result. + use super::prelude::{Account, Status}; +/// A struct containing results of a search. #[derive(Debug, Clone, Deserialize)] pub struct SearchResult { + /// An array of matched Accounts. pub accounts: Vec, + /// An array of matched Statuses. pub statuses: Vec, + /// An array of matched hashtags, as strings. pub hashtags: Vec, } diff --git a/src/entities/status.rs b/src/entities/status.rs index 3d59605..94f2a4b 100644 --- a/src/entities/status.rs +++ b/src/entities/status.rs @@ -1,47 +1,85 @@ +//! Module containing all info relating to a status. + use chrono::prelude::*; use super::prelude::*; use status_builder::Visibility; +/// A status from the instance. #[derive(Debug, Clone, Deserialize)] pub struct Status { + /// The ID of the status. pub id: i64, + /// A Fediverse-unique resource ID. pub uri: String, + /// URL to the status page (can be remote) pub url: String, + /// The Account which posted the status. pub account: Account, + /// The ID of the status this status is replying to, if the status is + /// a reply. pub in_reply_to_id: Option, + /// The ID of the account this status is replying to, if the status is + /// a reply. pub in_reply_to_account_id: Option, + /// If this status is a reblogged Status of another User. pub reblog: Option>, + /// Body of the status; this will contain HTML + /// (remote HTML already sanitized) pub content: String, + /// The time the status was created. pub created_at: DateTime, + /// The number of reblogs for the status. pub reblogs_count: u64, + /// The number of favourites for the status. pub favourites_count: u64, + /// Whether the application client has reblogged the status. pub reblogged: Option, + /// Whether the application client has favourited the status. pub favourited: Option, - pub sensitive: Option, + /// Whether media attachments should be hidden by default. + pub sensitive: bool, + /// If not empty, warning text that should be displayed before the actual + /// content. pub spoiler_text: String, + /// The visibilty of the status. pub visibility: Visibility, + /// An array of attachments. pub media_attachments: Vec, + /// An array of mentions. pub mentions: Vec, + /// An array of tags. pub tags: Vec, + /// Name of application used to post status. pub application: Option, } +/// A mention of another user. #[derive(Debug, Clone, Deserialize)] pub struct Mention { + /// URL of user's profile (can be remote). pub url: String, + /// The username of the account. pub username: String, + /// Equals `username` for local users, includes `@domain` for remote ones. pub acct: String, + /// Account ID. pub id: u64, } +/// Hashtags in the status. #[derive(Debug, Clone, Deserialize)] pub struct Tag { + /// The hashtag, not including the preceding `#`. pub name: String, + /// The URL of the hashtag. pub url: String, } +/// Application details. #[derive(Debug, Clone, Deserialize)] pub struct Application { + /// Name of the application. pub name: String, + /// Homepage URL of the application. pub website: Option, } diff --git a/src/lib.rs b/src/lib.rs index 1e8f686..c771ed4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ //! ``` #![cfg_attr(test, deny(warnings))] +#![cfg_attr(test, deny(missing_docs))] #[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_json as json; @@ -64,6 +65,7 @@ use entities::prelude::*; pub use status_builder::StatusBuilder; pub use registration::Registration; +/// Convience type over `std::result::Result` with `Error` as the error type. pub type Result = std::result::Result; macro_rules! methods { @@ -213,6 +215,7 @@ macro_rules! route_id { } +/// Your mastodon application client, handles all requests to and from Mastodon. #[derive(Clone, Debug)] pub struct Mastodon { client: Client, @@ -225,10 +228,15 @@ pub struct Mastodon { /// to authenticate on every run. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Data { + /// Base url of instance eg. `https://mastodon.social`. pub base: Cow<'static, str>, + /// The client's id given by the instance. pub client_id: Cow<'static, str>, + /// The client's secret given by the instance. pub client_secret: Cow<'static, str>, + /// Url to redirect back to your application from the instance signup. pub redirect: Cow<'static, str>, + /// The client's access token. pub token: Cow<'static, str>, } @@ -382,6 +390,7 @@ impl Mastodon { (delete) delete_status: "statuses/{}" => Empty, } + /// Post a new status to the account. pub fn new_status(&self, status: StatusBuilder) -> Result { use std::io::Read; @@ -400,6 +409,7 @@ impl Mastodon { } } + /// Get the federated timeline for the instance. pub fn get_public_timeline(&self, local: bool) -> Result> { let mut url = self.route("/api/v1/timelines/public"); @@ -410,6 +420,8 @@ impl Mastodon { self.get(url) } + /// Get timeline filtered by a hashtag(eg. `#coffee`) either locally or + /// federated. pub fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result> { let mut url = self.route("/api/v1/timelines/tag/"); url += &hashtag; @@ -421,6 +433,8 @@ impl Mastodon { self.get(url) } + /// Get statuses of a single account by id. Optionally only with pictures + /// and or excluding replies. pub fn statuses(&self, id: u64, only_media: bool, exclude_replies: bool) -> Result> { @@ -444,6 +458,8 @@ impl Mastodon { } + /// Returns the client account's relationship to a list of other accounts. + /// Such as whether they follow them or vice versa. pub fn relationships(&self, ids: &[u64]) -> Result> { let mut url = self.route("/api/v1/accounts/relationships?"); @@ -462,11 +478,15 @@ impl Mastodon { self.get(url) } + /// Search for accounts by their name. + /// Will lookup an account remotely if the search term is in the + /// `username@domain` format and not yet in the database. // TODO: Add a limit fn pub fn search_accounts(&self, query: &str) -> Result> { self.get(format!("{}/api/v1/accounts/search?q={}", self.base, query)) } + /// Returns the current Instance. pub fn instance(&self) -> Result { self.get(self.route("/api/v1/instance")) } diff --git a/src/registration.rs b/src/registration.rs index 0407e1a..9c44326 100644 --- a/src/registration.rs +++ b/src/registration.rs @@ -27,6 +27,10 @@ struct AccessToken { } impl Registration { + /// Construct a new registration process to the instance of the `base` url. + /// ``` + /// let registration = Registration::new("https://mastodon.social"); + /// ``` pub fn new>(base: I) -> Self { Registration { base: base.into(), @@ -107,6 +111,8 @@ impl Registration { } } + /// Create an access token from the client id, client secret, and code + /// provided by the authorisation url. pub fn create_access_token(self, code: String) -> Result { self.is_registered()?; let url = format!( diff --git a/src/status_builder.rs b/src/status_builder.rs index e733d0d..ff8845c 100644 --- a/src/status_builder.rs +++ b/src/status_builder.rs @@ -1,19 +1,26 @@ +/// A builder pattern struct for constructing a status. #[derive(Debug, Default, Clone, Serialize)] pub struct StatusBuilder { + /// The text of the status. pub status: String, - /// User ids of those to reply to. + /// Ids of accounts being replied to. #[serde(skip_serializing_if="Option::is_none")] pub in_reply_to_id: Option, + /// Ids of media attachments being attached to the status. #[serde(skip_serializing_if="Option::is_none")] pub media_ids: Option>, + /// Whether current status is sensitive. #[serde(skip_serializing_if="Option::is_none")] pub sensitive: Option, + /// Text to precede the normal status text. #[serde(skip_serializing_if="Option::is_none")] pub spoiler_text: Option, + /// Visibility of the status, defaults to `Public`. #[serde(skip_serializing_if="Option::is_none")] pub visibility: Option, } +/// The visibility of a status. #[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub enum Visibility { /// A Direct message to a user @@ -32,6 +39,10 @@ pub enum Visibility { impl StatusBuilder { + /// Create a new status with text. + /// ``` + /// let status = StatusBuilder::new("Hello World!".into()); + /// ``` pub fn new(status: String) -> Self { StatusBuilder { status: status,