summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Woolcock <paul@woolcock.us>2018-08-31 16:06:55 -0400
committerPaul Woolcock <paul@woolcock.us>2018-09-01 07:33:12 -0400
commita57c7e2f91eb9608e256850b17c03c9594d59c60 (patch)
tree991fc93ec4a7ec7a9f8b5766cae47169c2ad69fb
parent6befd79935ed40a5082d87d59651f9a1eab2f336 (diff)
feat(update_credentials): Implement UpdateCredsRequest
This will now allow a user to actually call the MastodonClient::update_credentials method
-rw-r--r--src/entities/account.rs149
-rw-r--r--src/entities/mod.rs2
-rw-r--r--src/lib.rs5
-rw-r--r--src/mastodon_client.rs4
-rw-r--r--src/requests/mod.rs9
-rw-r--r--src/requests/update_credentials.rs276
6 files changed, 310 insertions, 135 deletions
diff --git a/src/entities/account.rs b/src/entities/account.rs
index e787df5..1a8061a 100644
--- a/src/entities/account.rs
+++ b/src/entities/account.rs
@@ -1,10 +1,9 @@
//! A module containing everything relating to a account returned from the api.
use chrono::prelude::*;
-use reqwest::multipart::Form;
use serde::de::{self, Deserialize, Deserializer, Unexpected};
-use std::path::Path;
-use Result;
+use status_builder;
+use std::path::PathBuf;
/// A struct representing an Account.
#[derive(Debug, Clone, Deserialize)]
@@ -51,7 +50,7 @@ pub struct Account {
/// An extra object given from `verify_credentials` giving defaults about a user
#[derive(Debug, Clone, Deserialize)]
pub struct Source {
- privacy: ::status_builder::Visibility,
+ privacy: status_builder::Visibility,
#[serde(deserialize_with = "string_or_bool")]
sensitive: bool,
note: String,
@@ -82,130 +81,24 @@ fn string_or_bool<'de, D: Deserializer<'de>>(val: D) -> ::std::result::Result<bo
})
}
-/// Data structure used for updating user credentials
-#[derive(Debug)]
-pub struct CredentialsBuilder<'a> {
- display_name: Option<&'a str>,
- note: Option<&'a str>,
- avatar: Option<&'a Path>,
- header: Option<&'a Path>,
+#[derive(Debug, Default, Clone, Copy, Serialize)]
+pub(crate) struct UpdateSource {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) privacy: Option<status_builder::Visibility>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) sensitive: Option<bool>,
}
-impl<'a> CredentialsBuilder<'a> {
- /// Turns a `CredentialsForm` into a form suitable for PUTing to the
- /// endpoint
- pub fn into_form(self) -> Result<Form> {
- let mut form = Form::new();
- macro_rules! add_to_form {
- ($key:ident : Text; $($rest:tt)*) => {{
- if let Some(val) = self.$key {
- form = form.text(stringify!($key), val.to_owned());
- }
-
- add_to_form!{$($rest)*}
- }};
-
- ($key:ident : File; $($rest:tt)*) => {{
- if let Some(val) = self.$key {
- form = form.file(stringify!($key), val)?;
- }
-
- add_to_form!{$($rest)*}
- }};
-
- () => {}
- }
-
- add_to_form! {
- display_name: Text;
- note: Text;
- avatar: File;
- header: File;
- }
-
- Ok(form)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use tempfile::NamedTempFile;
-
- #[test]
- fn test_credentials_builder_to_form() {
- let avatar = NamedTempFile::new().expect("Couldn't make avatar file");
- let header = NamedTempFile::new().expect("Couldn't make header file");
- let tests = [
- (None, None, None, None),
- (Some("my-display-name"), None, None, None),
- (None, Some("my-note"), None, None),
- (None, None, Some(avatar.path().clone()), None),
- (None, None, None, Some(header.path().clone())),
- (Some("my-display-name"), Some("my-note"), None, None),
- (
- Some("my-display-name"),
- None,
- Some(avatar.path().clone()),
- None,
- ),
- (None, Some("my-note"), Some(avatar.path().clone()), None),
- (None, Some("my-note"), None, Some(header.path().clone())),
- (
- None,
- None,
- Some(avatar.path().clone()),
- Some(header.path().clone()),
- ),
- (
- Some("my-display-name"),
- None,
- None,
- Some(header.path().clone()),
- ),
- (
- Some("my-display-name"),
- Some("my-note"),
- Some(avatar.path().clone()),
- None,
- ),
- (
- Some("my-display-name"),
- Some("my-note"),
- None,
- Some(header.path().clone()),
- ),
- (
- Some("my-display-name"),
- None,
- Some(avatar.path().clone()),
- Some(header.path().clone()),
- ),
- (
- None,
- Some("my-note"),
- Some(avatar.path().clone()),
- Some(header.path().clone()),
- ),
- (
- Some("my-display-name"),
- Some("my-note"),
- Some(avatar.path().clone()),
- Some(header.path().clone()),
- ),
- ];
-
- for test in tests.into_iter() {
- let (display_name, note, avatar, header) = test;
- let credentials_builder = CredentialsBuilder {
- display_name: *display_name,
- note: *note,
- avatar: *avatar,
- header: *header,
- };
- let _form = credentials_builder
- .into_form()
- .expect("could not create form");
- }
- }
+#[derive(Debug, Default, Serialize)]
+pub(crate) struct Credentials {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) display_name: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) note: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) avatar: Option<PathBuf>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) header: Option<PathBuf>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub(crate) source: Option<UpdateSource>,
}
diff --git a/src/entities/mod.rs b/src/entities/mod.rs
index 9d73d8b..fc47b3e 100644
--- a/src/entities/mod.rs
+++ b/src/entities/mod.rs
@@ -33,7 +33,7 @@ pub struct Empty {}
/// modules:
pub mod prelude {
pub use super::{
- account::{Account, CredentialsBuilder, Source},
+ account::{Account, Source},
attachment::{Attachment, MediaType},
card::Card,
context::Context,
diff --git a/src/lib.rs b/src/lib.rs
index bdc962b..da2f109 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -80,7 +80,7 @@ pub use data::Data;
pub use errors::{ApiError, Error, Result};
pub use mastodon_client::MastodonClient;
pub use registration::Registration;
-pub use requests::statuses::StatusesRequest;
+pub use requests::{StatusesRequest, UpdateCredsRequest};
pub use status_builder::StatusBuilder;
/// Registering your App
@@ -207,7 +207,8 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
(delete) delete_status: "statuses/{}" => Empty,
}
- fn update_credentials(&self, changes: CredentialsBuilder) -> Result<Account> {
+ fn update_credentials(&self, builder: &mut UpdateCredsRequest) -> Result<Account> {
+ let changes = builder.build()?;
let url = self.route("/api/v1/accounts/update_credentials");
let response = self.send(self.client.patch(&url).json(&changes))?;
diff --git a/src/mastodon_client.rs b/src/mastodon_client.rs
index d183321..1d923a0 100644
--- a/src/mastodon_client.rs
+++ b/src/mastodon_client.rs
@@ -4,7 +4,7 @@ use entities::prelude::*;
use errors::Result;
use http_send::{HttpSend, HttpSender};
use page::Page;
-use requests::statuses::StatusesRequest;
+use requests::{StatusesRequest, UpdateCredsRequest};
use status_builder::StatusBuilder;
/// Represents the set of methods that a Mastodon Client can do, so that
@@ -172,7 +172,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
unimplemented!("This method was not implemented");
}
/// PATCH /api/v1/accounts/update_credentials
- fn update_credentials(&self, changes: CredentialsBuilder) -> Result<Account> {
+ fn update_credentials(&self, builder: &mut UpdateCredsRequest) -> Result<Account> {
unimplemented!("This method was not implemented");
}
/// POST /api/v1/statuses
diff --git a/src/requests/mod.rs b/src/requests/mod.rs
index f323806..bb3f1ae 100644
--- a/src/requests/mod.rs
+++ b/src/requests/mod.rs
@@ -1,2 +1,7 @@
-/// Data structures for the MastodonClient::statuses method
-pub mod statuses;
+/// Data structure for the MastodonClient::statuses method
+pub use self::statuses::StatusesRequest;
+/// Data structure for the MastodonClient::update_credentials method
+pub use self::update_credentials::UpdateCredsRequest;
+
+mod statuses;
+mod update_credentials;
diff --git a/src/requests/update_credentials.rs b/src/requests/update_credentials.rs
new file mode 100644
index 0000000..52a80df
--- /dev/null
+++ b/src/requests/update_credentials.rs
@@ -0,0 +1,276 @@
+use std::{
+ fmt::Display,
+ path::{Path, PathBuf},
+};
+
+use entities::account::{Credentials, UpdateSource};
+use errors::Result;
+use status_builder;
+
+/// Builder to pass to the Mastodon::update_credentials method
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate elefren;
+/// # use elefren::Data;
+/// # fn main() -> Result<(), elefren::Error> {
+/// # let data = Data {
+/// # base: "".into(),
+/// # client_id: "".into(),
+/// # client_secret: "".into(),
+/// # redirect: "".into(),
+/// # token: "".into(),
+/// # };
+/// use elefren::{prelude::*, status_builder::Visibility, UpdateCredsRequest};
+///
+/// let client = Mastodon::from(data);
+/// let mut builder = UpdateCredsRequest::new();
+///
+/// builder.privacy(Visibility::Unlisted);
+///
+/// let result = client.update_credentials(&mut builder)?;
+/// # Ok(())
+/// # }
+/// ```
+#[derive(Debug, Default, Clone, PartialEq)]
+pub struct UpdateCredsRequest {
+ display_name: Option<String>,
+ note: Option<String>,
+ avatar: Option<PathBuf>,
+ header: Option<PathBuf>,
+
+ // UpdateSource fields
+ privacy: Option<status_builder::Visibility>,
+ sensitive: Option<bool>,
+}
+
+impl UpdateCredsRequest {
+ /// Create a new UpdateCredsRequest
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::UpdateCredsRequest;
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ /// ```
+ pub fn new() -> UpdateCredsRequest {
+ Default::default()
+ }
+
+ /// Set the new display_name value
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::UpdateCredsRequest;
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ ///
+ /// builder.display_name("my new display name");
+ /// ```
+ pub fn display_name<D: Display>(&mut self, name: D) -> &mut Self {
+ self.display_name = Some(name.to_string());
+ self
+ }
+
+ /// Set the new note value
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::UpdateCredsRequest;
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ ///
+ /// builder.note("my new note");
+ /// ```
+ pub fn note<D: Display>(&mut self, note: D) -> &mut Self {
+ self.note = Some(note.to_string());
+ self
+ }
+
+ /// Set the new avatar value
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::UpdateCredsRequest;
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ ///
+ /// builder.avatar("/path/to/my/new/avatar");
+ /// ```
+ pub fn avatar<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+ let path = path.as_ref();
+ let path = path.to_path_buf();
+ self.avatar = Some(path);
+ self
+ }
+
+ /// Set the new header value
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::UpdateCredsRequest;
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ ///
+ /// builder.header("/path/to/my/new/header");
+ /// ```
+ pub fn header<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+ let path = path.as_ref();
+ let path = path.to_path_buf();
+ self.header = Some(path);
+ self
+ }
+
+ /// Set the new privacy value
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::{status_builder::Visibility, UpdateCredsRequest};
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ ///
+ /// builder.privacy(Visibility::Public);
+ /// ```
+ pub fn privacy(&mut self, privacy: status_builder::Visibility) -> &mut Self {
+ self.privacy = Some(privacy);
+ self
+ }
+
+ /// Set the new sensitive value
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate elefren;
+ /// use elefren::UpdateCredsRequest;
+ ///
+ /// let mut builder = UpdateCredsRequest::new();
+ ///
+ /// builder.sensitive(true);
+ /// ```
+ pub fn sensitive(&mut self, sensitive: bool) -> &mut Self {
+ self.sensitive = Some(sensitive);
+ self
+ }
+
+ pub(crate) fn build(&mut self) -> Result<Credentials> {
+ Ok(Credentials {
+ display_name: self.display_name.clone(),
+ note: self.note.clone(),
+ avatar: self.avatar.clone(),
+ header: self.avatar.clone(),
+ source: Some(UpdateSource {
+ privacy: self.privacy.clone(),
+ sensitive: self.sensitive.clone(),
+ }),
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use status_builder::Visibility;
+
+ #[test]
+ fn test_update_creds_request_new() {
+ let builder = UpdateCredsRequest::new();
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn test_update_creds_request_display_name() {
+ let mut builder = UpdateCredsRequest::new();
+ builder.display_name("foo");
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ display_name: Some("foo".into()),
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn test_update_creds_request_note() {
+ let mut builder = UpdateCredsRequest::new();
+ builder.note("foo");
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ note: Some("foo".into()),
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn test_update_creds_request_avatar() {
+ let mut builder = UpdateCredsRequest::new();
+ builder.avatar("/path/to/avatar.png");
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ avatar: Some(Path::new("/path/to/avatar.png").to_path_buf()),
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn test_update_creds_request_header() {
+ let mut builder = UpdateCredsRequest::new();
+ builder.header("/path/to/header.png");
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ header: Some(Path::new("/path/to/header.png").to_path_buf()),
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn test_update_creds_request_privacy() {
+ let mut builder = UpdateCredsRequest::new();
+ builder.privacy(Visibility::Public);
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ privacy: Some(Visibility::Public),
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn test_update_creds_request_sensitive() {
+ let mut builder = UpdateCredsRequest::new();
+ builder.sensitive(true);
+ assert_eq!(
+ builder,
+ UpdateCredsRequest {
+ sensitive: Some(true),
+ ..Default::default()
+ }
+ );
+ }
+}