feat(update_credentials): Implement UpdateCredsRequest
This will now allow a user to actually call the MastodonClient::update_credentials method
This commit is contained in:
+21
-128
@@ -1,10 +1,9 @@
|
|||||||
//! A module containing everything relating to a account returned from the api.
|
//! A module containing everything relating to a account returned from the api.
|
||||||
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use reqwest::multipart::Form;
|
|
||||||
use serde::de::{self, Deserialize, Deserializer, Unexpected};
|
use serde::de::{self, Deserialize, Deserializer, Unexpected};
|
||||||
use std::path::Path;
|
use status_builder;
|
||||||
use Result;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// A struct representing an Account.
|
/// A struct representing an Account.
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
@@ -51,7 +50,7 @@ pub struct Account {
|
|||||||
/// An extra object given from `verify_credentials` giving defaults about a user
|
/// An extra object given from `verify_credentials` giving defaults about a user
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct Source {
|
pub struct Source {
|
||||||
privacy: ::status_builder::Visibility,
|
privacy: status_builder::Visibility,
|
||||||
#[serde(deserialize_with = "string_or_bool")]
|
#[serde(deserialize_with = "string_or_bool")]
|
||||||
sensitive: bool,
|
sensitive: bool,
|
||||||
note: String,
|
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, Default, Clone, Copy, Serialize)]
|
||||||
#[derive(Debug)]
|
pub(crate) struct UpdateSource {
|
||||||
pub struct CredentialsBuilder<'a> {
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
display_name: Option<&'a str>,
|
pub(crate) privacy: Option<status_builder::Visibility>,
|
||||||
note: Option<&'a str>,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
avatar: Option<&'a Path>,
|
pub(crate) sensitive: Option<bool>,
|
||||||
header: Option<&'a Path>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CredentialsBuilder<'a> {
|
#[derive(Debug, Default, Serialize)]
|
||||||
/// Turns a `CredentialsForm` into a form suitable for PUTing to the
|
pub(crate) struct Credentials {
|
||||||
/// endpoint
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub fn into_form(self) -> Result<Form> {
|
pub(crate) display_name: Option<String>,
|
||||||
let mut form = Form::new();
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
macro_rules! add_to_form {
|
pub(crate) note: Option<String>,
|
||||||
($key:ident : Text; $($rest:tt)*) => {{
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
if let Some(val) = self.$key {
|
pub(crate) avatar: Option<PathBuf>,
|
||||||
form = form.text(stringify!($key), val.to_owned());
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
}
|
pub(crate) header: Option<PathBuf>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
add_to_form!{$($rest)*}
|
pub(crate) source: Option<UpdateSource>,
|
||||||
}};
|
|
||||||
|
|
||||||
($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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ pub struct Empty {}
|
|||||||
/// modules:
|
/// modules:
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::{
|
pub use super::{
|
||||||
account::{Account, CredentialsBuilder, Source},
|
account::{Account, Source},
|
||||||
attachment::{Attachment, MediaType},
|
attachment::{Attachment, MediaType},
|
||||||
card::Card,
|
card::Card,
|
||||||
context::Context,
|
context::Context,
|
||||||
|
|||||||
+3
-2
@@ -80,7 +80,7 @@ pub use data::Data;
|
|||||||
pub use errors::{ApiError, Error, Result};
|
pub use errors::{ApiError, Error, Result};
|
||||||
pub use mastodon_client::MastodonClient;
|
pub use mastodon_client::MastodonClient;
|
||||||
pub use registration::Registration;
|
pub use registration::Registration;
|
||||||
pub use requests::statuses::StatusesRequest;
|
pub use requests::{StatusesRequest, UpdateCredsRequest};
|
||||||
pub use status_builder::StatusBuilder;
|
pub use status_builder::StatusBuilder;
|
||||||
|
|
||||||
/// Registering your App
|
/// Registering your App
|
||||||
@@ -207,7 +207,8 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
|||||||
(delete) delete_status: "statuses/{}" => Empty,
|
(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 url = self.route("/api/v1/accounts/update_credentials");
|
||||||
let response = self.send(self.client.patch(&url).json(&changes))?;
|
let response = self.send(self.client.patch(&url).json(&changes))?;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use entities::prelude::*;
|
|||||||
use errors::Result;
|
use errors::Result;
|
||||||
use http_send::{HttpSend, HttpSender};
|
use http_send::{HttpSend, HttpSender};
|
||||||
use page::Page;
|
use page::Page;
|
||||||
use requests::statuses::StatusesRequest;
|
use requests::{StatusesRequest, UpdateCredsRequest};
|
||||||
use status_builder::StatusBuilder;
|
use status_builder::StatusBuilder;
|
||||||
|
|
||||||
/// Represents the set of methods that a Mastodon Client can do, so that
|
/// 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");
|
unimplemented!("This method was not implemented");
|
||||||
}
|
}
|
||||||
/// PATCH /api/v1/accounts/update_credentials
|
/// 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");
|
unimplemented!("This method was not implemented");
|
||||||
}
|
}
|
||||||
/// POST /api/v1/statuses
|
/// POST /api/v1/statuses
|
||||||
|
|||||||
+7
-2
@@ -1,2 +1,7 @@
|
|||||||
/// Data structures for the MastodonClient::statuses method
|
/// Data structure for the MastodonClient::statuses method
|
||||||
pub mod statuses;
|
pub use self::statuses::StatusesRequest;
|
||||||
|
/// Data structure for the MastodonClient::update_credentials method
|
||||||
|
pub use self::update_credentials::UpdateCredsRequest;
|
||||||
|
|
||||||
|
mod statuses;
|
||||||
|
mod update_credentials;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user