[fractal] API, directory: Separate endpoint connection from query build
- From: Christopher Davis <christopherdavis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] API, directory: Separate endpoint connection from query build
- Date: Tue, 20 Aug 2019 20:56:27 +0000 (UTC)
commit 962143c95d749cb2dbbb9bf57dd6ec210dade448
Author: Alejandro DomÃnguez <adomu net-c com>
Date: Fri Feb 1 23:01:06 2019 +0100
API, directory: Separate endpoint connection from query build
fractal-gtk/src/appop/directory.rs | 2 +-
fractal-matrix-api/src/backend/directory.rs | 178 ++++++++++++---------
fractal-matrix-api/src/backend/mod.rs | 4 +-
fractal-matrix-api/src/backend/types.rs | 2 +-
fractal-matrix-api/src/lib.rs | 2 +
fractal-matrix-api/src/meson.build | 7 +-
fractal-matrix-api/src/model/mod.rs | 1 -
fractal-matrix-api/src/model/room.rs | 56 +------
fractal-matrix-api/src/r0.rs | 2 +
fractal-matrix-api/src/r0/directory.rs | 1 +
.../src/r0/directory/post_public_rooms.rs | 80 +++++++++
fractal-matrix-api/src/r0/thirdparty.rs | 1 +
.../thirdparty/get_supported_protocols.rs} | 22 ++-
fractal-matrix-api/src/ser.rs | 12 ++
fractal-matrix-api/src/types.rs | 6 -
fractal-matrix-api/src/util.rs | 2 +-
16 files changed, 228 insertions(+), 150 deletions(-)
---
diff --git a/fractal-gtk/src/appop/directory.rs b/fractal-gtk/src/appop/directory.rs
index 733fd2ef..79f982d0 100644
--- a/fractal-gtk/src/appop/directory.rs
+++ b/fractal-gtk/src/appop/directory.rs
@@ -7,8 +7,8 @@ use crate::appop::AppOp;
use crate::backend::BKCommand;
use crate::widgets;
-use crate::types::ProtocolInstance;
use crate::types::Room;
+use fractal_api::r0::thirdparty::get_supported_protocols::ProtocolInstance;
impl AppOp {
pub fn init_protocols(&self) {
diff --git a/fractal-matrix-api/src/backend/directory.rs b/fractal-matrix-api/src/backend/directory.rs
index 99ce826e..b54b8cda 100644
--- a/fractal-matrix-api/src/backend/directory.rs
+++ b/fractal-matrix-api/src/backend/directory.rs
@@ -1,6 +1,4 @@
-use serde_json::json;
-use serde_json::Value as JsonValue;
-use url::Url;
+use url::{Host, Url};
use crate::globals;
@@ -10,45 +8,52 @@ use crate::error::Error;
use std::thread;
use crate::util::cache_path;
-use crate::util::json_q;
use crate::util::media;
-
-use crate::types::PublicRoomsFilter;
-use crate::types::PublicRoomsRequest;
-use crate::types::PublicRoomsResponse;
+use crate::util::HTTP_CLIENT;
+
+use crate::r0::directory::post_public_rooms::request as post_public_rooms;
+use crate::r0::directory::post_public_rooms::Body as PublicRoomsBody;
+use crate::r0::directory::post_public_rooms::Filter as PublicRoomsFilter;
+use crate::r0::directory::post_public_rooms::Parameters as PublicRoomsParameters;
+use crate::r0::directory::post_public_rooms::Response as PublicRoomsResponse;
+use crate::r0::directory::post_public_rooms::ThirdPartyNetworks;
+use crate::r0::thirdparty::get_supported_protocols::request as get_supported_protocols;
+use crate::r0::thirdparty::get_supported_protocols::Parameters as SupportedProtocolsParameters;
+use crate::r0::thirdparty::get_supported_protocols::Response as SupportedProtocolsResponse;
use crate::types::Room;
-use crate::types::SupportedProtocols;
-use crate::types::ThirdPartyNetworks;
pub fn protocols(bk: &Backend) {
- let baseu = bk.get_base_url();
- let tk = bk.data.lock().unwrap().access_token.clone();
- let mut url = baseu
- .join("/_matrix/client/r0/thirdparty/protocols")
- .expect("Wrong URL in protocols()");
- url.query_pairs_mut()
- .clear()
- .append_pair("access_token", &tk);
-
let tx = bk.tx.clone();
- get!(
- &url,
- move |r: JsonValue| {
- let protocols = serde_json::from_value(r)
- .map(|protocols: SupportedProtocols| {
- protocols
- .into_iter()
- .flat_map(|(_, protocol)| protocol.instances.into_iter())
- .collect()
- })
- .unwrap_or_default();
-
- tx.send(BKResponse::DirectoryProtocols(protocols)).unwrap();
- },
- |err| {
- tx.send(BKResponse::DirectoryError(err)).unwrap();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+
+ let base = bk.get_base_url();
+ let params = SupportedProtocolsParameters { access_token };
+
+ thread::spawn(move || {
+ let query = get_supported_protocols(base, ¶ms)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<SupportedProtocolsResponse>()
+ .map_err(Into::into)
+ });
+
+ match query {
+ Ok(response) => {
+ let protocols = response
+ .into_iter()
+ .flat_map(|(_, protocol)| protocol.instances.into_iter())
+ .collect();
+
+ let _ = tx.send(BKResponse::DirectoryProtocols(protocols));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::DirectoryError(err));
+ }
}
- );
+ });
}
pub fn room_search(
@@ -58,69 +63,84 @@ pub fn room_search(
third_party: Option<String>,
more: bool,
) -> Result<(), Error> {
- let mut params: Vec<(&str, String)> = Vec::new();
-
- if let Some(mut hs) = homeserver {
- // Extract the hostname if `homeserver` is an URL
- if let Ok(homeserver_url) = Url::parse(&hs) {
- hs = homeserver_url.host_str().unwrap_or_default().to_string();
- }
+ let tx = bk.tx.clone();
+ let data = bk.data.clone();
- params.push(("server", hs));
- }
+ // TODO: use transpose() when it is stabilized
+ let server = homeserver
+ .map(|hs| {
+ Url::parse(&hs)
+ .ok()
+ .as_ref()
+ .and_then(Url::host)
+ .as_ref()
+ .map(Host::to_owned)
+ .map(Ok)
+ .unwrap_or(Host::parse(&hs))
+ .map(Some)
+ })
+ .unwrap_or(Ok(None))?;
- let url = bk.url("publicRooms", params)?;
let base = bk.get_base_url();
+ let access_token = data.lock().unwrap().access_token.clone();
let since = if more {
- Some(bk.data.lock().unwrap().rooms_since.clone())
+ Some(data.lock().unwrap().rooms_since.clone())
} else {
None
};
- let request = PublicRoomsRequest {
+ let params = PublicRoomsParameters {
+ access_token,
+ server,
+ };
+
+ let body = PublicRoomsBody {
limit: Some(globals::ROOM_DIRECTORY_LIMIT),
filter: Some(PublicRoomsFilter {
generic_search_term,
}),
since,
third_party_networks: third_party
- .map(|tp| ThirdPartyNetworks::Only(tp))
+ .map(ThirdPartyNetworks::Only)
.unwrap_or_default(),
};
- let attrs = serde_json::to_value(request).expect("Failed to serialize the search request");
-
- let tx = bk.tx.clone();
- let data = bk.data.clone();
- post!(
- &url,
- &attrs,
- move |r: JsonValue| {
- let rooms = serde_json::from_value(r)
- .map(|pr: PublicRoomsResponse| {
- data.lock().unwrap().rooms_since = pr.next_batch.unwrap_or_default();
-
- pr.chunk
- .into_iter()
- .map(Into::into)
- .inspect(|r: &Room| {
- if let Some(avatar) = r.avatar.clone() {
- if let Ok(dest) = cache_path(&r.id) {
- media(&base.clone(), &avatar, Some(&dest)).unwrap_or_default();
- }
+ thread::spawn(move || {
+ let query = post_public_rooms(base.clone(), ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<PublicRoomsResponse>()
+ .map_err(Into::into)
+ });
+
+ match query {
+ Ok(response) => {
+ data.lock().unwrap().rooms_since = response.next_batch.unwrap_or_default();
+
+ let rooms = response
+ .chunk
+ .into_iter()
+ .map(Into::into)
+ .inspect(|r: &Room| {
+ if let Some(avatar) = r.avatar.clone() {
+ if let Ok(dest) = cache_path(&r.id) {
+ let _ = media(&base, &avatar, Some(&dest));
}
- })
- .collect()
- })
- .unwrap_or_default();
-
- tx.send(BKResponse::DirectorySearch(rooms)).unwrap();
- },
- |err| {
- tx.send(BKResponse::DirectoryError(err)).unwrap();
+ }
+ })
+ .collect();
+
+ let _ = tx.send(BKResponse::DirectorySearch(rooms));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::DirectoryError(err));
+ }
}
- );
+ });
Ok(())
}
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 78137ae7..39c6c80d 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -303,9 +303,7 @@ impl Backend {
}
// Directory module
- Ok(BKCommand::DirectoryProtocols) => {
- directory::protocols(self);
- }
+ Ok(BKCommand::DirectoryProtocols) => directory::protocols(self),
Ok(BKCommand::DirectorySearch(dhs, dq, dtp, more)) => {
let hs = match dhs {
ref a if a.is_empty() => None,
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index 76855c36..2b7f6704 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -4,11 +4,11 @@ use std::sync::{Arc, Condvar, Mutex};
use crate::error::Error;
+use crate::r0::thirdparty::get_supported_protocols::ProtocolInstance;
use crate::types::Event;
use crate::types::Medium;
use crate::types::Member;
use crate::types::Message;
-use crate::types::ProtocolInstance;
use crate::types::Room;
use crate::types::Sticker;
use crate::types::StickerGroup;
diff --git a/fractal-matrix-api/src/lib.rs b/fractal-matrix-api/src/lib.rs
index a302385b..8f600d45 100644
--- a/fractal-matrix-api/src/lib.rs
+++ b/fractal-matrix-api/src/lib.rs
@@ -7,6 +7,8 @@ pub mod backend;
pub mod cache;
mod client;
mod model;
+pub mod r0;
+mod ser;
pub mod types;
#[cfg(test)]
diff --git a/fractal-matrix-api/src/meson.build b/fractal-matrix-api/src/meson.build
index 8e6eea47..958b39b7 100644
--- a/fractal-matrix-api/src/meson.build
+++ b/fractal-matrix-api/src/meson.build
@@ -14,17 +14,22 @@ api_sources = files(
'model/member.rs',
'model/message.rs',
'model/mod.rs',
- 'model/protocol.rs',
'model/register.rs',
'model/room.rs',
'model/stickers.rs',
'model/sync.rs',
'model/user.rs',
+ 'r0/directory/post_public_rooms.rs',
+ 'r0/thirdparty/get_supported_protocols.rs',
+ 'r0/directory.rs',
+ 'r0/thirdparty.rs',
'cache.rs',
'client.rs',
'error.rs',
'globals.rs',
'lib.rs',
+ 'r0.rs',
+ 'ser.rs',
'types.rs',
'util.rs'
)
diff --git a/fractal-matrix-api/src/model/mod.rs b/fractal-matrix-api/src/model/mod.rs
index 758a0e27..0a005e21 100644
--- a/fractal-matrix-api/src/model/mod.rs
+++ b/fractal-matrix-api/src/model/mod.rs
@@ -3,7 +3,6 @@ pub mod fileinfo;
pub mod filter;
pub mod member;
pub mod message;
-pub mod protocol;
pub mod register;
pub mod room;
pub mod stickers;
diff --git a/fractal-matrix-api/src/model/room.rs b/fractal-matrix-api/src/model/room.rs
index 6c30afaf..6e52517f 100644
--- a/fractal-matrix-api/src/model/room.rs
+++ b/fractal-matrix-api/src/model/room.rs
@@ -3,6 +3,7 @@ use serde_json::Value as JsonValue;
use crate::model::member::Member;
use crate::model::member::MemberList;
use crate::model::message::Message;
+use crate::r0::directory::post_public_rooms::Chunk as PublicRoomsChunk;
use crate::types::SyncResponse;
use crate::util::get_user_avatar;
use crate::util::parse_m_direct;
@@ -297,61 +298,6 @@ impl PartialEq for Room {
pub type RoomList = HashMap<String, Room>;
-#[derive(Clone, Debug, Serialize)]
-pub struct PublicRoomsRequest {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub limit: Option<i32>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub since: Option<String>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub filter: Option<PublicRoomsFilter>,
- #[serde(flatten)]
- pub third_party_networks: ThirdPartyNetworks,
-}
-
-#[derive(Clone, Debug, Serialize)]
-pub struct PublicRoomsFilter {
- pub generic_search_term: Option<String>,
-}
-
-#[derive(Clone, Debug, Serialize)]
-#[serde(tag = "include_all_networks", content = "third_party_instance_id")]
-pub enum ThirdPartyNetworks {
- #[serde(rename = "false")]
- None,
- #[serde(rename = "false")]
- Only(String),
- #[serde(rename = "true")]
- All,
-}
-
-impl Default for ThirdPartyNetworks {
- fn default() -> Self {
- ThirdPartyNetworks::None
- }
-}
-
-#[derive(Clone, Debug, Deserialize)]
-pub struct PublicRoomsResponse {
- pub chunk: Vec<PublicRoomsChunk>,
- pub next_batch: Option<String>,
- pub prev_batch: Option<String>,
- pub total_room_count_estimate: Option<u64>,
-}
-
-#[derive(Clone, Debug, Deserialize)]
-pub struct PublicRoomsChunk {
- pub aliases: Option<Vec<String>>,
- pub avatar_url: Option<String>,
- pub canonical_alias: Option<String>,
- pub guest_can_join: bool,
- pub name: Option<String>,
- pub num_joined_members: i32,
- pub room_id: String,
- pub topic: Option<String>,
- pub world_readable: bool,
-}
-
fn evc(events: &Vec<JsonValue>, t: &str, field: &str) -> Option<String> {
events
.iter()
diff --git a/fractal-matrix-api/src/r0.rs b/fractal-matrix-api/src/r0.rs
new file mode 100644
index 00000000..d87d88df
--- /dev/null
+++ b/fractal-matrix-api/src/r0.rs
@@ -0,0 +1,2 @@
+pub mod directory;
+pub mod thirdparty;
diff --git a/fractal-matrix-api/src/r0/directory.rs b/fractal-matrix-api/src/r0/directory.rs
new file mode 100644
index 00000000..b7b38fa4
--- /dev/null
+++ b/fractal-matrix-api/src/r0/directory.rs
@@ -0,0 +1 @@
+pub mod post_public_rooms;
diff --git a/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
b/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
new file mode 100644
index 00000000..145b7acb
--- /dev/null
+++ b/fractal-matrix-api/src/r0/directory/post_public_rooms.rs
@@ -0,0 +1,80 @@
+use crate::ser::serialize_option_host;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Host;
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+ #[serde(serialize_with = "serialize_option_host")]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub server: Option<Host<String>>,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub limit: Option<i32>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub since: Option<String>,
+ // This field doesn't follow the spec but for some reason
+ // it fails with matrix.org if it's not set this way
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub filter: Option<Filter>,
+ #[serde(flatten)]
+ pub third_party_networks: ThirdPartyNetworks,
+}
+
+#[derive(Clone, Debug, Serialize)]
+#[serde(tag = "include_all_networks", content = "third_party_instance_id")]
+pub enum ThirdPartyNetworks {
+ #[serde(rename = "false")]
+ None,
+ #[serde(rename = "false")]
+ Only(String),
+ #[serde(rename = "true")]
+ All,
+}
+
+impl Default for ThirdPartyNetworks {
+ fn default() -> Self {
+ ThirdPartyNetworks::None
+ }
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Filter {
+ pub generic_search_term: Option<String>,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub chunk: Vec<Chunk>,
+ pub next_batch: Option<String>,
+ pub prev_batch: Option<String>,
+ pub total_room_count_estimate: Option<u64>,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Chunk {
+ pub aliases: Option<Vec<String>>,
+ pub avatar_url: Option<String>,
+ pub canonical_alias: Option<String>,
+ pub guest_can_join: bool,
+ pub name: Option<String>,
+ pub num_joined_members: i32,
+ pub room_id: String,
+ pub topic: Option<String>,
+ pub world_readable: bool,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/publicRooms")
+ .expect("Malformed URL in post_public_rooms");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/thirdparty.rs b/fractal-matrix-api/src/r0/thirdparty.rs
new file mode 100644
index 00000000..b2338027
--- /dev/null
+++ b/fractal-matrix-api/src/r0/thirdparty.rs
@@ -0,0 +1 @@
+pub mod get_supported_protocols;
diff --git a/fractal-matrix-api/src/model/protocol.rs
b/fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
similarity index 57%
rename from fractal-matrix-api/src/model/protocol.rs
rename to fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
index 040ed1d8..65100d34 100644
--- a/fractal-matrix-api/src/model/protocol.rs
+++ b/fractal-matrix-api/src/r0/thirdparty/get_supported_protocols.rs
@@ -1,8 +1,17 @@
-use serde::Deserialize;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::collections::BTreeMap;
+use url::Url;
-pub type SupportedProtocols = BTreeMap<String, Protocol>;
+#[derive(Debug, Clone, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+pub type Response = BTreeMap<String, Protocol>;
#[derive(Debug, Clone, Deserialize)]
pub struct Protocol {
@@ -23,9 +32,18 @@ pub struct FieldType {
#[derive(Debug, Clone, Deserialize)]
pub struct ProtocolInstance {
+ // TODO: Avoid this rename
#[serde(rename = "network_id")]
pub id: String,
pub desc: String,
pub icon: Option<String>,
pub fields: JsonValue,
}
+
+pub fn request(base: Url, params: &Parameters) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/thirdparty/protocols")
+ .expect("Wrong URL in get_supported_protocols");
+
+ Client::new().get(url).query(params).build()
+}
diff --git a/fractal-matrix-api/src/ser.rs b/fractal-matrix-api/src/ser.rs
new file mode 100644
index 00000000..2029a499
--- /dev/null
+++ b/fractal-matrix-api/src/ser.rs
@@ -0,0 +1,12 @@
+use serde::Serializer;
+use url::Host;
+
+pub fn serialize_option_host<S>(host: &Option<Host>, ser: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+{
+ match host {
+ Some(h) => ser.serialize_str(&h.to_string()),
+ None => ser.serialize_none(),
+ }
+}
diff --git a/fractal-matrix-api/src/types.rs b/fractal-matrix-api/src/types.rs
index eb451f2c..3f6d76f5 100644
--- a/fractal-matrix-api/src/types.rs
+++ b/fractal-matrix-api/src/types.rs
@@ -8,18 +8,12 @@ pub use crate::model::filter::RoomFilter;
pub use crate::model::member::Member;
pub use crate::model::member::MemberList;
pub use crate::model::message::Message;
-pub use crate::model::protocol::ProtocolInstance;
-pub use crate::model::protocol::SupportedProtocols;
pub use crate::model::register::*;
-pub use crate::model::room::PublicRoomsFilter;
-pub use crate::model::room::PublicRoomsRequest;
-pub use crate::model::room::PublicRoomsResponse;
pub use crate::model::room::Reason;
pub use crate::model::room::Room;
pub use crate::model::room::RoomList;
pub use crate::model::room::RoomMembership;
pub use crate::model::room::RoomTag;
-pub use crate::model::room::ThirdPartyNetworks;
pub use crate::model::stickers::Sticker;
pub use crate::model::stickers::StickerGroup;
pub use crate::model::sync::JoinedRoom;
diff --git a/fractal-matrix-api/src/util.rs b/fractal-matrix-api/src/util.rs
index f4664fd2..bba8f3a3 100644
--- a/fractal-matrix-api/src/util.rs
+++ b/fractal-matrix-api/src/util.rs
@@ -29,7 +29,7 @@ use reqwest::header::CONTENT_TYPE;
use crate::globals;
lazy_static! {
- static ref HTTP_CLIENT: Client = Client::new();
+ pub static ref HTTP_CLIENT: Client = Client::new();
}
pub fn semaphore<F>(thread_count: Arc<(Mutex<u8>, Condvar)>, func: F)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]