reformat all, fix deps for tungstenite

update-deps
Ondřej Hruška 6 days ago
parent 79ce4ce378
commit 217277b162
  1. 10
      Cargo.toml
  2. 46
      src/debug.rs
  3. 24
      src/entities/attachment.rs
  4. 9
      src/entities/notification.rs
  5. 2
      src/entities/status.rs
  6. 5
      src/helpers/mod.rs
  7. 50
      src/lib.rs
  8. 2
      src/macros.rs
  9. 2
      src/media_builder.rs
  10. 4
      src/page.rs
  11. 11
      src/registration.rs
  12. 28
      src/streaming.rs
  13. 2
      src/unauth.rs

@ -13,7 +13,7 @@ edition = "2018"
[dependencies] [dependencies]
doc-comment = "0.3" doc-comment = "0.3"
hyper-old-types = "0.11.0" # Used to parse the link header hyper-old-types = "0.11.0" # Used to parse the link header
isolang = { version = "2.4", features = ["serde"] } isolang = { version = "2.4.0", features = ["serde"] }
log = "^0.4" log = "^0.4"
reqwest = { version = "0.12.18", default-features = false, features = ["json", "blocking", "multipart", "rustls-tls", "stream"] } reqwest = { version = "0.12.18", default-features = false, features = ["json", "blocking", "multipart", "rustls-tls", "stream"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
@ -21,10 +21,10 @@ serde_json = "1"
serde_urlencoded = "0.7.1" serde_urlencoded = "0.7.1"
serde_qs = "0.15.0" serde_qs = "0.15.0"
url = "2.5.4" url = "2.5.4"
toml = { version="0.8", features = ["parse"] } toml = { version = "0.8", features = ["parse"] }
tokio-tungstenite = "0.27" tokio-tungstenite = { version = "0.27", features = ["rustls-tls-webpki-roots"] }
tokio = {version = "1", features = [ "fs" ] } tokio = { version = "1", features = ["fs"] }
tokio-util = { version = "0.7", features = [ "io" ] } tokio-util = { version = "0.7", features = ["io"] }
tokio-stream = "0.1.17" tokio-stream = "0.1.17"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
thiserror = "2" thiserror = "2"

@ -1,7 +1,7 @@
use crate::entities::event::Event;
use crate::entities::notification::{Notification, NotificationType}; use crate::entities::notification::{Notification, NotificationType};
use crate::entities::status::Status; use crate::entities::status::Status;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use crate::entities::event::Event;
pub struct NotificationDisplay<'a>(pub &'a Notification); pub struct NotificationDisplay<'a>(pub &'a Notification);
@ -10,32 +10,42 @@ impl<'a> Display for NotificationDisplay<'a> {
let n = self.0; let n = self.0;
match &n.notification_type { match &n.notification_type {
NotificationType::Follow => { NotificationType::Follow => {
write!(f, "Follow {{ #{}, @{} }}", n.id, n.account.acct ) write!(f, "Follow {{ #{}, @{} }}", n.id, n.account.acct)
} }
NotificationType::Favourite => { NotificationType::Favourite => {
if let Some(ref s) = n.status { if let Some(ref s) = n.status {
write!(f, "Favourite {{ #{}, acct: @{}, status: «{}» }}", n.id, n.account.acct, s.content ) write!(
f,
"Favourite {{ #{}, acct: @{}, status: «{}» }}",
n.id, n.account.acct, s.content
)
} else { } else {
write!(f, "Favourite {{ #{}, acct: @{}, status: -- }}", n.id, n.account.acct ) write!(f, "Favourite {{ #{}, acct: @{}, status: -- }}", n.id, n.account.acct)
} }
} }
NotificationType::Mention => { NotificationType::Mention => {
if let Some(ref s) = n.status { if let Some(ref s) = n.status {
write!(f, "Mention {{ #{}, acct: @{}, status: «{}» }}", n.id, n.account.acct, s.content ) write!(
f,
"Mention {{ #{}, acct: @{}, status: «{}» }}",
n.id, n.account.acct, s.content
)
} else { } else {
write!(f, "Mention {{ #{}, acct: @{}, status: -- }}", n.id, n.account.acct ) write!(f, "Mention {{ #{}, acct: @{}, status: -- }}", n.id, n.account.acct)
} }
} }
NotificationType::Reblog => { NotificationType::Reblog => {
if let Some(ref s) = n.status { if let Some(ref s) = n.status {
write!(f, "Reblog {{ #{}, acct: @{}, status: «{}» }}", n.id, n.account.acct, s.content ) write!(
f,
"Reblog {{ #{}, acct: @{}, status: «{}» }}",
n.id, n.account.acct, s.content
)
} else { } else {
write!(f, "Reblog {{ #{}, acct: @{}, status: -- }}", n.id, n.account.acct ) write!(f, "Reblog {{ #{}, acct: @{}, status: -- }}", n.id, n.account.acct)
}
} }
NotificationType::Other(other) => {
f.write_str(&other)
} }
NotificationType::Other(other) => f.write_str(&other),
} }
} }
} }
@ -46,9 +56,7 @@ impl<'a> Display for EventDisplay<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let n = self.0; let n = self.0;
match n { match n {
Event::Notification(n) => { Event::Notification(n) => NotificationDisplay(n).fmt(f),
NotificationDisplay(n).fmt(f)
}
Event::Delete(id) => { Event::Delete(id) => {
write!(f, "Delete {{ #{} }}", id) write!(f, "Delete {{ #{} }}", id)
} }
@ -58,9 +66,7 @@ impl<'a> Display for EventDisplay<'a> {
Event::Heartbeat => { Event::Heartbeat => {
write!(f, "Heartbeat") write!(f, "Heartbeat")
} }
Event::Update(s) => { Event::Update(s) => StatusDisplay(s).fmt(f),
StatusDisplay(s).fmt(f)
}
} }
} }
} }
@ -69,6 +75,10 @@ pub struct StatusDisplay<'a>(pub &'a Status);
impl<'a> Display for StatusDisplay<'a> { impl<'a> Display for StatusDisplay<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Status {{ #{}, acct: @{}, status: «{}», vis: {:?} }}", self.0.id, self.0.account.acct, self.0.content, self.0.visibility ) write!(
f,
"Status {{ #{}, acct: @{}, status: «{}», vis: {:?} }}",
self.0.id, self.0.account.acct, self.0.content, self.0.visibility
)
} }
} }

@ -71,8 +71,8 @@ pub enum MediaType {
Other(String), Other(String),
} }
use std::str::FromStr;
use serde::de::{value, Deserializer, IntoDeserializer}; use serde::de::{value, Deserializer, IntoDeserializer};
use std::str::FromStr;
impl FromStr for MediaType { impl FromStr for MediaType {
type Err = value::Error; type Err = value::Error;
@ -84,12 +84,11 @@ impl FromStr for MediaType {
impl<'de> Deserialize<'de> for MediaType { impl<'de> Deserialize<'de> for MediaType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> where
D: Deserializer<'de>,
{ {
let s = String::deserialize(deserializer)?; let s = String::deserialize(deserializer)?;
let deserialized = Self::from_str(&s).unwrap_or_else(|_| { let deserialized = Self::from_str(&s).unwrap_or_else(|_| Self::Other(s));
Self::Other(s)
});
Ok(deserialized) Ok(deserialized)
} }
} }
@ -101,8 +100,17 @@ mod tests {
#[test] #[test]
fn test_deserialize_media_type() { fn test_deserialize_media_type() {
assert_eq!(MediaType::Image, serde_json::from_value(Value::String("image".to_owned())).unwrap()); assert_eq!(
assert_eq!(MediaType::Audio, serde_json::from_value(Value::String("audio".to_owned())).unwrap()); MediaType::Image,
assert_eq!(MediaType::Other("pleroma_weird_thing".to_string()), serde_json::from_value(Value::String("pleroma_weird_thing".to_owned())).unwrap()); serde_json::from_value(Value::String("image".to_owned())).unwrap()
);
assert_eq!(
MediaType::Audio,
serde_json::from_value(Value::String("audio".to_owned())).unwrap()
);
assert_eq!(
MediaType::Other("pleroma_weird_thing".to_string()),
serde_json::from_value(Value::String("pleroma_weird_thing".to_owned())).unwrap()
);
} }
} }

@ -39,8 +39,8 @@ pub enum NotificationType {
Other(String), Other(String),
} }
use std::str::FromStr;
use serde::de::{value, Deserializer, IntoDeserializer}; use serde::de::{value, Deserializer, IntoDeserializer};
use std::str::FromStr;
impl FromStr for NotificationType { impl FromStr for NotificationType {
type Err = value::Error; type Err = value::Error;
@ -52,12 +52,11 @@ impl FromStr for NotificationType {
impl<'de> Deserialize<'de> for NotificationType { impl<'de> Deserialize<'de> for NotificationType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> where
D: Deserializer<'de>,
{ {
let s = String::deserialize(deserializer)?; let s = String::deserialize(deserializer)?;
let deserialized = Self::from_str(&s).unwrap_or_else(|_| { let deserialized = Self::from_str(&s).unwrap_or_else(|_| Self::Other(s));
Self::Other(s)
});
Ok(deserialized) Ok(deserialized)
} }
} }

File diff suppressed because one or more lines are too long

@ -23,11 +23,12 @@ pub mod json;
/// Helpers for working with the command line /// Helpers for working with the command line
pub mod cli; pub mod cli;
/// # Low-level API for extending /// # Low-level API for extending
// Convert the HTTP response body from JSON. Pass up deserialization errors // Convert the HTTP response body from JSON. Pass up deserialization errors
// transparently. // transparently.
pub async fn deserialise_response<T: for<'de> serde::Deserialize<'de>>(response: reqwest::Response) -> crate::Result<T> { pub async fn deserialise_response<T: for<'de> serde::Deserialize<'de>>(
response: reqwest::Response,
) -> crate::Result<T> {
let bytes = response.bytes().await?; let bytes = response.bytes().await?;
match serde_json::from_slice(&bytes) { match serde_json::from_slice(&bytes) {
Ok(t) => { Ok(t) => {

@ -19,25 +19,14 @@ use reqwest::multipart;
use entities::prelude::*; use entities::prelude::*;
pub use errors::{Error, Result}; pub use errors::{Error, Result};
use helpers::deserialise_response; use helpers::deserialise_response;
use serde::{Serialize,Deserialize}; use requests::{AddFilterRequest, AddPushRequest, StatusesRequest, UpdateCredsRequest, UpdatePushRequest};
use requests::{ use serde::{Deserialize, Serialize};
AddFilterRequest,
AddPushRequest,
StatusesRequest,
UpdateCredsRequest,
UpdatePushRequest,
};
use streaming::EventReader; use streaming::EventReader;
pub use streaming::StreamKind; pub use streaming::StreamKind;
pub use crate::{ pub use crate::{
data::AppData, data::AppData, media_builder::MediaBuilder, page::Page, registration::Registration, scopes::Scopes,
media_builder::MediaBuilder, status_builder::NewStatus, status_builder::StatusBuilder,
page::Page,
registration::Registration,
scopes::Scopes,
status_builder::NewStatus,
status_builder::StatusBuilder,
}; };
#[macro_use] #[macro_use]
@ -64,10 +53,10 @@ pub mod requests;
pub mod scopes; pub mod scopes;
/// Constructing a status /// Constructing a status
pub mod status_builder; pub mod status_builder;
/// Client that doesn't need auth
pub mod unauth;
/// Streaming API /// Streaming API
pub mod streaming; pub mod streaming;
/// Client that doesn't need auth
pub mod unauth;
pub mod debug; pub mod debug;
@ -88,12 +77,12 @@ impl From<AppData> for FediClient {
} }
} }
#[derive(Serialize,Deserialize,Clone,Copy,PartialEq)] #[derive(Serialize, Deserialize, Clone, Copy, PartialEq)]
#[serde(rename_all="snake_case")] #[serde(rename_all = "snake_case")]
pub enum SearchType { pub enum SearchType {
Accounts, Accounts,
Hashtags, Hashtags,
Statuses Statuses,
} }
impl FediClient { impl FediClient {
@ -246,7 +235,9 @@ impl FediClient {
/// Post a new status to the account. /// Post a new status to the account.
pub async fn new_status(&self, status: NewStatus) -> Result<Status> { pub async fn new_status(&self, status: NewStatus) -> Result<Status> {
let response = self.send(self.http_client.post(&self.route("/api/v1/statuses")).json(&status)).await?; let response = self
.send(self.http_client.post(&self.route("/api/v1/statuses")).json(&status))
.await?;
deserialise_response(response).await deserialise_response(response).await
} }
@ -306,7 +297,9 @@ impl FediClient {
/// Add a push notifications subscription /// Add a push notifications subscription
pub async fn add_push_subscription(&self, request: &AddPushRequest) -> Result<Subscription> { pub async fn add_push_subscription(&self, request: &AddPushRequest) -> Result<Subscription> {
let request = request.build()?; let request = request.build()?;
let response = self.send(self.http_client.post(&self.route("/api/v1/push/subscription")).json(&request)).await?; let response = self
.send(self.http_client.post(&self.route("/api/v1/push/subscription")).json(&request))
.await?;
deserialise_response(response).await deserialise_response(response).await
} }
@ -315,7 +308,9 @@ impl FediClient {
/// access token /// access token
pub async fn update_push_data(&self, request: &UpdatePushRequest) -> Result<Subscription> { pub async fn update_push_data(&self, request: &UpdatePushRequest) -> Result<Subscription> {
let request = request.build(); let request = request.build();
let response = self.send(self.http_client.put(&self.route("/api/v1/push/subscription")).json(&request)).await?; let response = self
.send(self.http_client.put(&self.route("/api/v1/push/subscription")).json(&request))
.await?;
deserialise_response(response).await deserialise_response(response).await
} }
@ -332,7 +327,6 @@ impl FediClient {
self.following(&me.id).await self.following(&me.id).await
} }
/// returns events that are relevant to the authorized user, i.e. home /// returns events that are relevant to the authorized user, i.e. home
/// timeline & notifications /// timeline & notifications
pub async fn streaming_user(&self) -> Result<EventReader> { pub async fn streaming_user(&self) -> Result<EventReader> {
@ -380,7 +374,8 @@ impl FediClient {
let mut form = multipart::Form::new(); let mut form = multipart::Form::new();
form = match media.data { form = match media.data {
MediaBuilderData::Reader(reader) => { MediaBuilderData::Reader(reader) => {
let mut part = multipart::Part::stream(reqwest::Body::wrap_stream(tokio_util::io::ReaderStream::new(reader))); let mut part =
multipart::Part::stream(reqwest::Body::wrap_stream(tokio_util::io::ReaderStream::new(reader)));
if let Some(filename) = media.filename { if let Some(filename) = media.filename {
part = part.file_name(filename); part = part.file_name(filename);
} }
@ -406,7 +401,9 @@ impl FediClient {
form = form.text("focus", format!("{},{}", x, y)); form = form.text("focus", format!("{},{}", x, y));
} }
let response = self.send(self.http_client.post(&self.route("/api/v1/media")).multipart(form)).await?; let response = self
.send(self.http_client.post(&self.route("/api/v1/media")).multipart(form))
.await?;
deserialise_response(response).await deserialise_response(response).await
} }
@ -454,4 +451,3 @@ impl ClientBuilder {
}) })
} }
} }

@ -215,7 +215,7 @@ macro_rules! route_v1_id {
self.$method(self.route(&format!(concat!("/api/v1/", $url), id))).await self.$method(self.route(&format!(concat!("/api/v1/", $url), id))).await
} }
} }
} };
} }
macro_rules! route_v1_paged_id { macro_rules! route_v1_paged_id {
(($method:ident) $name:ident: $url:expr => $ret:ty) => { (($method:ident) $name:ident: $url:expr => $ret:ty) => {

@ -1,7 +1,7 @@
use std::fmt; use std::fmt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tokio::io::AsyncRead;
use std::pin::Pin; use std::pin::Pin;
use tokio::io::AsyncRead;
#[derive(Debug)] #[derive(Debug)]
/// A builder pattern struct for preparing a single attachment for upload. /// A builder pattern struct for preparing a single attachment for upload.

@ -1,7 +1,7 @@
use super::{deserialise_response, FediClient, Result}; use super::{deserialise_response, FediClient, Result};
use crate::entities::itemsiter::ItemsIter; use crate::entities::itemsiter::ItemsIter;
use hyper_old_types::header::{parsing, Link, RelationType}; use hyper_old_types::header::{parsing, Link, RelationType};
use reqwest::{Response, header::LINK}; use reqwest::{header::LINK, Response};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
@ -82,7 +82,7 @@ impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
initial_items: deserialise_response(response).await?, initial_items: deserialise_response(response).await?,
next, next,
prev, prev,
api_client: api_client, api_client,
}) })
} }
} }

@ -1,11 +1,11 @@
use std::borrow::Cow; use std::borrow::Cow;
use crate::apps::{App, AppBuilder};
use crate::data::AppData;
use crate::scopes::Scopes;
use crate::{ClientBuilder, Error, FediClient, Result};
use serde::Deserialize; use serde::Deserialize;
use std::convert::TryInto; use std::convert::TryInto;
use crate::apps::{AppBuilder, App};
use crate::scopes::Scopes;
use crate::{Result, Error, FediClient, ClientBuilder};
use crate::data::AppData;
const DEFAULT_REDIRECT_URI: &str = "urn:ietf:wg:oauth:2.0:oob"; const DEFAULT_REDIRECT_URI: &str = "urn:ietf:wg:oauth:2.0:oob";
@ -127,8 +127,7 @@ impl<'a> Registration<'a> {
async fn send_app(&self, app: &App) -> Result<OAuth> { async fn send_app(&self, app: &App) -> Result<OAuth> {
let url = format!("{}/api/v1/apps", self.base); let url = format!("{}/api/v1/apps", self.base);
Ok(self.send(self.http_client.post(url).json(&app)).await? Ok(self.send(self.http_client.post(url).json(&app)).await?.json().await?)
.json().await?)
} }
} }

@ -1,14 +1,14 @@
use crate::{Error, Result};
use tokio_tungstenite::{WebSocketStream, MaybeTlsStream};
use tokio::net::TcpStream;
use tokio_stream::Stream;
use crate::entities::event::Event; use crate::entities::event::Event;
use std::pin::Pin;
use std::task::Poll;
use tokio_tungstenite::tungstenite::Message;
use crate::entities::notification::Notification; use crate::entities::notification::Notification;
use crate::entities::status::Status; use crate::entities::status::Status;
use crate::{Error, Result};
use futures_util::sink::SinkExt; use futures_util::sink::SinkExt;
use std::pin::Pin;
use std::task::Poll;
use tokio::net::TcpStream;
use tokio_stream::Stream;
use tokio_tungstenite::tungstenite::Message;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum StreamKind<'a> { pub enum StreamKind<'a> {
@ -53,14 +53,13 @@ impl<'a> StreamKind<'a> {
StreamKind::Public => vec![], StreamKind::Public => vec![],
StreamKind::PublicLocal => vec![], StreamKind::PublicLocal => vec![],
StreamKind::Direct => vec![], StreamKind::Direct => vec![],
StreamKind::Hashtag(tag) StreamKind::Hashtag(tag) | StreamKind::HashtagLocal(tag) => vec![("tag", tag)],
| StreamKind::HashtagLocal(tag) => vec![("tag", tag)],
StreamKind::List(list) => vec![("tag", list)], StreamKind::List(list) => vec![("tag", list)],
} }
} }
} }
pub(crate) async fn do_open_streaming(url : &str) -> Result<EventReader> { pub(crate) async fn do_open_streaming(url: &str) -> Result<EventReader> {
let mut url: url::Url = reqwest::get(url).await?.url().as_str().parse()?; let mut url: url::Url = reqwest::get(url).await?.url().as_str().parse()?;
let new_scheme = match url.scheme() { let new_scheme = match url.scheme() {
"http" => "ws", "http" => "ws",
@ -84,10 +83,7 @@ pub struct EventReader {
impl EventReader { impl EventReader {
fn new(stream: WebSocketStream<MaybeTlsStream<TcpStream>>) -> Self { fn new(stream: WebSocketStream<MaybeTlsStream<TcpStream>>) -> Self {
Self { Self { stream, lines: vec![] }
stream,
lines: vec![]
}
} }
pub async fn send_ping(&mut self) -> std::result::Result<(), tokio_tungstenite::tungstenite::Error> { pub async fn send_ping(&mut self) -> std::result::Result<(), tokio_tungstenite::tungstenite::Error> {
@ -143,9 +139,7 @@ impl Stream for EventReader {
// Stream is closed // Stream is closed
Poll::Ready(None) Poll::Ready(None)
} }
Poll::Pending => { Poll::Pending => Poll::Pending,
Poll::Pending
}
Poll::Ready(Some(Ok(Message::Frame(_)))) => { Poll::Ready(Some(Ok(Message::Frame(_)))) => {
unreachable!(); unreachable!();
} }

@ -1,9 +1,9 @@
use crate::{Result, streaming};
use crate::entities::card::Card; use crate::entities::card::Card;
use crate::entities::context::Context; use crate::entities::context::Context;
use crate::entities::status::Status; use crate::entities::status::Status;
use crate::helpers::deserialise_response; use crate::helpers::deserialise_response;
use crate::streaming::EventReader; use crate::streaming::EventReader;
use crate::{streaming, Result};
/// Client that can make unauthenticated calls to a mastodon instance /// Client that can make unauthenticated calls to a mastodon instance
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

Loading…
Cancel
Save