Compare commits
2 Commits
6adc0c1fbb
...
d68e3eca3b
| Author | SHA1 | Date | |
|---|---|---|---|
| d68e3eca3b | |||
| 3640f72d73 |
11
src/main.rs
11
src/main.rs
@@ -57,18 +57,17 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.route("/api", web::get().to(api::api_home))
|
.route("/api", web::get().to(api::api_home))
|
||||||
.route("/api", web::post().to(api::api_home))
|
.route("/api", web::post().to(api::api_home))
|
||||||
.route("/api/account/whoami", web::get().to(api::account::who_am_i))
|
.route("/api/account/whoami", web::get().to(api::account::who_am_i))
|
||||||
.route("/api/room/{room_id}/name", web::get().to(api::room::name))
|
.route("/api/room/{room_id}", web::get().to(api::room::info))
|
||||||
.route(
|
|
||||||
"/api/room/{room_id}/avatar",
|
|
||||||
web::get().to(api::room::avatar),
|
|
||||||
)
|
|
||||||
.route(
|
.route(
|
||||||
"/api/media/{server_name}/{media_id}/download",
|
"/api/media/{server_name}/{media_id}/download",
|
||||||
web::get().to(api::media::download),
|
web::get().to(api::media::download),
|
||||||
)
|
)
|
||||||
// TODO : handle media thumbnail
|
// TODO : handle media thumbnail
|
||||||
// TODO : handle space
|
// TODO : handle space
|
||||||
// TODO : handle user information
|
.route(
|
||||||
|
"/api/profile/{user_id}",
|
||||||
|
web::get().to(api::profile::get_profile),
|
||||||
|
)
|
||||||
.service(web::resource("/api/ws").route(web::get().to(api::ws::ws)))
|
.service(web::resource("/api/ws").route(web::get().to(api::ws::ws)))
|
||||||
})
|
})
|
||||||
.workers(4)
|
.workers(4)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use actix_web::HttpResponse;
|
|||||||
|
|
||||||
pub mod account;
|
pub mod account;
|
||||||
pub mod media;
|
pub mod media;
|
||||||
|
pub mod profile;
|
||||||
pub mod room;
|
pub mod room;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
|
|
||||||
|
|||||||
29
src/server/api/profile.rs
Normal file
29
src/server/api/profile.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use crate::extractors::client_auth::APIClientAuth;
|
||||||
|
use crate::server::HttpResult;
|
||||||
|
use crate::utils::matrix_utils::ApiMxcURI;
|
||||||
|
use actix_web::{web, HttpResponse};
|
||||||
|
use ruma::api::client::profile;
|
||||||
|
use ruma::OwnedUserId;
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct UserIDInPath {
|
||||||
|
user_id: OwnedUserId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize)]
|
||||||
|
struct ProfileResponse {
|
||||||
|
display_name: Option<String>,
|
||||||
|
avatar: Option<ApiMxcURI>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get user profile
|
||||||
|
pub async fn get_profile(auth: APIClientAuth, path: web::Path<UserIDInPath>) -> HttpResult {
|
||||||
|
let res = auth
|
||||||
|
.send_request(profile::get_profile::v3::Request::new(path.user_id.clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(ProfileResponse {
|
||||||
|
display_name: res.displayname,
|
||||||
|
avatar: res.avatar_url.map(ApiMxcURI),
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::extractors::client_auth::APIClientAuth;
|
use crate::extractors::client_auth::APIClientAuth;
|
||||||
use crate::server::HttpResult;
|
use crate::server::{HttpFailure, HttpResult};
|
||||||
use crate::utils::matrix_utils::parse_mxc_url;
|
use crate::utils::matrix_utils::ApiMxcURI;
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use ruma::api::client::state;
|
use ruma::api::client::state;
|
||||||
use ruma::events::StateEventType;
|
use ruma::events::StateEventType;
|
||||||
use ruma::{OwnedRoomId, OwnedServerName};
|
use ruma::{OwnedMxcUri, OwnedRoomId};
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct RoomIDInPath {
|
pub struct RoomIDInPath {
|
||||||
@@ -12,50 +13,53 @@ pub struct RoomIDInPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
struct GetRoomNameResponse {
|
struct GetRoomInfoResponse {
|
||||||
name: String,
|
name: Option<String>,
|
||||||
|
avatar: Option<ApiMxcURI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get room name
|
/// Get a room information
|
||||||
pub async fn name(auth: APIClientAuth, path: web::Path<RoomIDInPath>) -> HttpResult {
|
async fn get_room_info<E: DeserializeOwned>(
|
||||||
|
auth: &APIClientAuth,
|
||||||
|
room_id: OwnedRoomId,
|
||||||
|
event_type: StateEventType,
|
||||||
|
field: &str,
|
||||||
|
) -> anyhow::Result<Option<E>, HttpFailure> {
|
||||||
let res = auth
|
let res = auth
|
||||||
.send_request(state::get_state_events_for_key::v3::Request::new(
|
.send_request(state::get_state_events_for_key::v3::Request::new(
|
||||||
|
room_id,
|
||||||
|
event_type,
|
||||||
|
String::default(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(res.content.get_field(field)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get room information
|
||||||
|
pub async fn info(auth: APIClientAuth, path: web::Path<RoomIDInPath>) -> HttpResult {
|
||||||
|
let room_name: Option<String> = get_room_info(
|
||||||
|
&auth,
|
||||||
path.room_id.clone(),
|
path.room_id.clone(),
|
||||||
StateEventType::RoomName,
|
StateEventType::RoomName,
|
||||||
String::default(),
|
"name",
|
||||||
))
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(GetRoomNameResponse {
|
let room_avatar: Option<OwnedMxcUri> = get_room_info(
|
||||||
name: res.content.get_field("name")?.unwrap_or("").to_string(),
|
&auth,
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
|
||||||
struct GetRoomAvatarResponse {
|
|
||||||
url: String,
|
|
||||||
server_name: OwnedServerName,
|
|
||||||
media_id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get room avatar
|
|
||||||
pub async fn avatar(auth: APIClientAuth, path: web::Path<RoomIDInPath>) -> HttpResult {
|
|
||||||
let res = auth
|
|
||||||
.send_request(state::get_state_events_for_key::v3::Request::new(
|
|
||||||
path.room_id.clone(),
|
path.room_id.clone(),
|
||||||
StateEventType::RoomAvatar,
|
StateEventType::RoomAvatar,
|
||||||
String::default(),
|
"url",
|
||||||
))
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
|
|
||||||
let avatar_url = res.content.get_field("url")?.unwrap_or("").to_string();
|
Ok(HttpResponse::Ok().json(GetRoomInfoResponse {
|
||||||
let Some((media_id, server_name)) = parse_mxc_url(&avatar_url) else {
|
name: room_name,
|
||||||
return Ok(HttpResponse::InternalServerError().body("Invalid Matrix resource URL"));
|
avatar: room_avatar.map(ApiMxcURI),
|
||||||
};
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(GetRoomAvatarResponse {
|
|
||||||
url: avatar_url.to_string(),
|
|
||||||
server_name,
|
|
||||||
media_id: media_id.to_string(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
use ruma::OwnedServerName;
|
use ruma::OwnedMxcUri;
|
||||||
use std::str::FromStr;
|
use serde::ser::SerializeMap;
|
||||||
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
/// Parse Matrix media URL returning media id and server name
|
pub struct ApiMxcURI(pub OwnedMxcUri);
|
||||||
pub fn parse_mxc_url(url: &str) -> Option<(&str, OwnedServerName)> {
|
|
||||||
let strip = url.strip_prefix("mxc://")?;
|
|
||||||
let parts = strip.split_once('/')?;
|
|
||||||
|
|
||||||
Some((parts.0, OwnedServerName::from_str(parts.1).ok()?))
|
impl Serialize for ApiMxcURI {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut map = serializer.serialize_map(Some(3))?;
|
||||||
|
map.serialize_entry("uri", &self.0)?;
|
||||||
|
map.serialize_entry("server_name", &self.0.server_name().ok())?;
|
||||||
|
map.serialize_entry("media_id", &self.0.media_id().ok())?;
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user