fix: send full state after joining a room

This commit is contained in:
timokoesters 2020-04-29 12:18:45 +02:00
parent 8087ddd746
commit 169dbe6c37
No known key found for this signature in database
GPG key ID: 24DA7517711A2BA4
6 changed files with 134 additions and 69 deletions

View file

@ -13,9 +13,10 @@ use ruma_client_api::{
filter::{self, create_filter, get_filter}, filter::{self, create_filter, get_filter},
keys::{get_keys, upload_keys}, keys::{get_keys, upload_keys},
membership::{ membership::{
get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias, forget_room, leave_room, forget_room, get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias,
leave_room,
}, },
message::{get_message_events, create_message_event}, message::{create_message_event, get_message_events},
presence::set_presence, presence::set_presence,
profile::{ profile::{
get_avatar_url, get_display_name, get_profile, set_avatar_url, set_display_name, get_avatar_url, get_display_name, get_profile, set_avatar_url, set_display_name,
@ -673,16 +674,18 @@ pub fn join_room_by_id_or_alias_route(
) -> MatrixResult<join_room_by_id_or_alias::Response> { ) -> MatrixResult<join_room_by_id_or_alias::Response> {
let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) { let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) {
Ok(room_id) => room_id, Ok(room_id) => room_id,
Err(room_alias) => if room_alias.server_name() == data.hostname() { Err(room_alias) => {
return MatrixResult(Err(Error { if room_alias.server_name() == data.hostname() {
kind: ErrorKind::NotFound, return MatrixResult(Err(Error {
message: "Room alias not found.".to_owned(), kind: ErrorKind::NotFound,
status_code: http::StatusCode::NOT_FOUND, message: "Room alias not found.".to_owned(),
})); status_code: http::StatusCode::NOT_FOUND,
} else { }));
// Ask creator server of the room to join TODO ask someone else when not available } else {
//server_server::send_request(data, destination, request) // Ask creator server of the room to join TODO ask someone else when not available
todo!(); //server_server::send_request(data, destination, request)
todo!();
}
} }
}; };
@ -762,7 +765,7 @@ pub async fn get_public_rooms_filtered_route(
.and_then(|s| s.content.get("name")) .and_then(|s| s.content.get("name"))
.and_then(|n| n.as_str()) .and_then(|n| n.as_str())
.map(|n| n.to_owned()), .map(|n| n.to_owned()),
num_joined_members: data.room_users(&room_id).into(), num_joined_members: data.room_users_joined(&room_id).into(),
room_id, room_id,
topic: None, topic: None,
world_readable: false, world_readable: false,
@ -917,19 +920,37 @@ pub fn sync_route(
body: Ruma<sync_events::Request>, body: Ruma<sync_events::Request>,
) -> MatrixResult<sync_events::Response> { ) -> MatrixResult<sync_events::Response> {
std::thread::sleep(Duration::from_millis(300)); std::thread::sleep(Duration::from_millis(300));
let user_id = body.user_id.clone().expect("user is authenticated");
let next_batch = data.last_pdu_index().to_string(); let next_batch = data.last_pdu_index().to_string();
let mut joined_rooms = BTreeMap::new(); let mut joined_rooms = BTreeMap::new();
let joined_roomids = data.rooms_joined(body.user_id.as_ref().expect("user is authenticated")); let joined_roomids = data.rooms_joined(&user_id);
let since = body let since = body
.since .since
.clone() .clone()
.and_then(|string| string.parse().ok()) .and_then(|string| string.parse().ok())
.unwrap_or(0); .unwrap_or(0);
for room_id in joined_roomids { for room_id in joined_roomids {
let pdus = data.pdus_since(&room_id, since); let pdus = data.pdus_since(&room_id, since);
let room_events = pdus.into_iter().map(|pdu| pdu.to_room_event()).collect::<Vec<_>>();
let is_first_pdu = data.room_pdu_first(&room_id, since); let mut send_member_count = false;
let mut send_full_state = false;
for pdu in &pdus {
if pdu.kind == EventType::RoomMember {
if pdu.state_key == Some(user_id.to_string()) && pdu.content["membership"] == "join"
{
send_full_state = true;
}
send_member_count = true;
}
}
let room_events = pdus
.into_iter()
.map(|pdu| pdu.to_room_event())
.collect::<Vec<_>>();
let mut edus = data.roomlatests_since(&room_id, since); let mut edus = data.roomlatests_since(&room_id, since);
edus.extend_from_slice(&data.roomactives_in(&room_id)); edus.extend_from_slice(&data.roomactives_in(&room_id));
@ -939,8 +960,16 @@ pub fn sync_route(
account_data: sync_events::AccountData { events: Vec::new() }, account_data: sync_events::AccountData { events: Vec::new() },
summary: sync_events::RoomSummary { summary: sync_events::RoomSummary {
heroes: Vec::new(), heroes: Vec::new(),
joined_member_count: None, joined_member_count: if send_member_count {
invited_member_count: None, Some(data.room_users_joined(&room_id).into())
} else {
None
},
invited_member_count: if send_member_count {
Some(data.room_users_invited(&room_id).into())
} else {
None
},
}, },
unread_notifications: sync_events::UnreadNotificationsCount { unread_notifications: sync_events::UnreadNotificationsCount {
highlight_count: None, highlight_count: None,
@ -951,14 +980,24 @@ pub fn sync_route(
prev_batch: Some(since.to_string()), prev_batch: Some(since.to_string()),
events: room_events, events: room_events,
}, },
state: sync_events::State { events: Vec::new() }, // TODO: state before timeline
state: sync_events::State {
events: if send_full_state {
data.room_state(&room_id)
.into_iter()
.map(|(_, pdu)| pdu.to_state_event())
.collect()
} else {
Vec::new()
},
},
ephemeral: sync_events::Ephemeral { events: edus }, ephemeral: sync_events::Ephemeral { events: edus },
}, },
); );
} }
let mut left_rooms = BTreeMap::new(); let mut left_rooms = BTreeMap::new();
let left_roomids = data.rooms_left(body.user_id.as_ref().expect("user is authenticated")); let left_roomids = data.rooms_left(&user_id);
for room_id in left_roomids { for room_id in left_roomids {
let pdus = data.pdus_since(&room_id, since); let pdus = data.pdus_since(&room_id, since);
let room_events = pdus.into_iter().map(|pdu| pdu.to_room_event()).collect(); let room_events = pdus.into_iter().map(|pdu| pdu.to_room_event()).collect();
@ -980,7 +1019,7 @@ pub fn sync_route(
} }
let mut invited_rooms = BTreeMap::new(); let mut invited_rooms = BTreeMap::new();
for room_id in data.rooms_invited(body.user_id.as_ref().expect("user is authenticated")) { for room_id in data.rooms_invited(&user_id) {
let events = data let events = data
.pdus_since(&room_id, since) .pdus_since(&room_id, since)
.into_iter() .into_iter()
@ -1013,15 +1052,18 @@ pub fn sync_route(
pub fn get_message_events_route( pub fn get_message_events_route(
data: State<Data>, data: State<Data>,
body: Ruma<get_message_events::Request>, body: Ruma<get_message_events::Request>,
_room_id: String) -> MatrixResult<get_message_events::Response> { _room_id: String,
if let get_message_events::Direction::Forward = body.dir {todo!();} ) -> MatrixResult<get_message_events::Response> {
if let get_message_events::Direction::Forward = body.dir {
todo!();
}
if let Ok(from) = body if let Ok(from) = body.from.clone().parse() {
.from
.clone()
.parse() {
let pdus = data.pdus_until(&body.room_id, from); let pdus = data.pdus_until(&body.room_id, from);
let room_events = pdus.into_iter().map(|pdu| pdu.to_room_event()).collect::<Vec<_>>(); let room_events = pdus
.into_iter()
.map(|pdu| pdu.to_room_event())
.collect::<Vec<_>>();
MatrixResult(Ok(get_message_events::Response { MatrixResult(Ok(get_message_events::Response {
start: Some(body.from.clone()), start: Some(body.from.clone()),
end: None, end: None,
@ -1058,7 +1100,9 @@ pub fn publicised_groups_route() -> MatrixResult<create_message_event::Response>
} }
#[options("/<_segments..>")] #[options("/<_segments..>")]
pub fn options_route(_segments: rocket::http::uri::Segments) -> MatrixResult<create_message_event::Response> { pub fn options_route(
_segments: rocket::http::uri::Segments,
) -> MatrixResult<create_message_event::Response> {
MatrixResult(Err(Error { MatrixResult(Err(Error {
kind: ErrorKind::NotFound, kind: ErrorKind::NotFound,
message: "This is the options route.".to_owned(), message: "This is the options route.".to_owned(),

View file

@ -193,11 +193,11 @@ impl Data {
return false; return false;
} }
self.db.userid_roomids.add( self.db.userid_joinroomids.add(
user_id.to_string().as_bytes(), user_id.to_string().as_bytes(),
room_id.to_string().as_bytes().into(), room_id.to_string().as_bytes().into(),
); );
self.db.roomid_userids.add( self.db.roomid_joinuserids.add(
room_id.to_string().as_bytes(), room_id.to_string().as_bytes(),
user_id.to_string().as_bytes().into(), user_id.to_string().as_bytes().into(),
); );
@ -205,6 +205,10 @@ impl Data {
user_id.to_string().as_bytes(), user_id.to_string().as_bytes(),
room_id.to_string().as_bytes(), room_id.to_string().as_bytes(),
); );
self.db.roomid_inviteuserids.remove_value(
user_id.to_string().as_bytes(),
room_id.to_string().as_bytes(),
);
self.db.userid_leftroomids.remove_value( self.db.userid_leftroomids.remove_value(
user_id.to_string().as_bytes(), user_id.to_string().as_bytes(),
room_id.to_string().as_bytes().into(), room_id.to_string().as_bytes().into(),
@ -232,7 +236,7 @@ impl Data {
pub fn rooms_joined(&self, user_id: &UserId) -> Vec<RoomId> { pub fn rooms_joined(&self, user_id: &UserId) -> Vec<RoomId> {
self.db self.db
.userid_roomids .userid_joinroomids
.get_iter(user_id.to_string().as_bytes()) .get_iter(user_id.to_string().as_bytes())
.values() .values()
.map(|room_id| { .map(|room_id| {
@ -282,9 +286,16 @@ impl Data {
room_ids room_ids
} }
pub fn room_users(&self, room_id: &RoomId) -> u32 { pub fn room_users_joined(&self, room_id: &RoomId) -> u32 {
self.db self.db
.roomid_userids .roomid_joinuserids
.get_iter(room_id.to_string().as_bytes())
.count() as u32
}
pub fn room_users_invited(&self, room_id: &RoomId) -> u32 {
self.db
.roomid_inviteuserids
.get_iter(room_id.to_string().as_bytes()) .get_iter(room_id.to_string().as_bytes())
.count() as u32 .count() as u32
} }
@ -324,11 +335,15 @@ impl Data {
user_id.to_string().as_bytes(), user_id.to_string().as_bytes(),
room_id.to_string().as_bytes().into(), room_id.to_string().as_bytes().into(),
); );
self.db.userid_roomids.remove_value( self.db.roomid_inviteuserids.remove_value(
user_id.to_string().as_bytes(), user_id.to_string().as_bytes(),
room_id.to_string().as_bytes().into(), room_id.to_string().as_bytes().into(),
); );
self.db.roomid_userids.remove_value( self.db.userid_joinroomids.remove_value(
user_id.to_string().as_bytes(),
room_id.to_string().as_bytes().into(),
);
self.db.roomid_joinuserids.remove_value(
room_id.to_string().as_bytes(), room_id.to_string().as_bytes(),
user_id.to_string().as_bytes().into(), user_id.to_string().as_bytes().into(),
); );
@ -358,7 +373,7 @@ impl Data {
user_id.to_string().as_bytes(), user_id.to_string().as_bytes(),
room_id.to_string().as_bytes().into(), room_id.to_string().as_bytes().into(),
); );
self.db.roomid_userids.add( self.db.roomid_inviteuserids.add(
room_id.to_string().as_bytes(), room_id.to_string().as_bytes(),
user_id.to_string().as_bytes().into(), user_id.to_string().as_bytes().into(),
); );

View file

@ -71,8 +71,9 @@ pub struct Database {
pub eventid_pduid: sled::Tree, pub eventid_pduid: sled::Tree,
pub roomid_pduleaves: MultiValue, pub roomid_pduleaves: MultiValue,
pub roomstateid_pdu: sled::Tree, // Room + StateType + StateKey pub roomstateid_pdu: sled::Tree, // Room + StateType + StateKey
pub roomid_userids: MultiValue, pub roomid_joinuserids: MultiValue,
pub userid_roomids: MultiValue, pub roomid_inviteuserids: MultiValue,
pub userid_joinroomids: MultiValue,
pub userid_inviteroomids: MultiValue, pub userid_inviteroomids: MultiValue,
pub userid_leftroomids: MultiValue, pub userid_leftroomids: MultiValue,
// EDUs: // EDUs:
@ -115,8 +116,9 @@ impl Database {
eventid_pduid: db.open_tree("eventid_pduid").unwrap(), eventid_pduid: db.open_tree("eventid_pduid").unwrap(),
roomid_pduleaves: MultiValue(db.open_tree("roomid_pduleaves").unwrap()), roomid_pduleaves: MultiValue(db.open_tree("roomid_pduleaves").unwrap()),
roomstateid_pdu: db.open_tree("roomstateid_pdu").unwrap(), roomstateid_pdu: db.open_tree("roomstateid_pdu").unwrap(),
roomid_userids: MultiValue(db.open_tree("roomid_userids").unwrap()), roomid_joinuserids: MultiValue(db.open_tree("roomid_joinuserids").unwrap()),
userid_roomids: MultiValue(db.open_tree("userid_roomids").unwrap()), roomid_inviteuserids: MultiValue(db.open_tree("roomid_inviteuserids").unwrap()),
userid_joinroomids: MultiValue(db.open_tree("userid_joinroomids").unwrap()),
userid_inviteroomids: MultiValue(db.open_tree("userid_inviteroomids").unwrap()), userid_inviteroomids: MultiValue(db.open_tree("userid_inviteroomids").unwrap()),
userid_leftroomids: MultiValue(db.open_tree("userid_leftroomids").unwrap()), userid_leftroomids: MultiValue(db.open_tree("userid_leftroomids").unwrap()),
roomlatestid_roomlatest: db.open_tree("roomlatestid_roomlatest").unwrap(), roomlatestid_roomlatest: db.open_tree("roomlatestid_roomlatest").unwrap(),
@ -200,7 +202,7 @@ impl Database {
); );
} }
println!("\n# RoomId -> UserIds:"); println!("\n# RoomId -> UserIds:");
for (k, v) in self.roomid_userids.iter_all().map(|r| r.unwrap()) { for (k, v) in self.roomid_joinuserids.iter_all().map(|r| r.unwrap()) {
println!( println!(
"{:?} -> {:?}", "{:?} -> {:?}",
String::from_utf8_lossy(&k), String::from_utf8_lossy(&k),
@ -208,7 +210,7 @@ impl Database {
); );
} }
println!("\n# UserId -> RoomIds:"); println!("\n# UserId -> RoomIds:");
for (k, v) in self.userid_roomids.iter_all().map(|r| r.unwrap()) { for (k, v) in self.userid_joinroomids.iter_all().map(|r| r.unwrap()) {
println!( println!(
"{:?} -> {:?}", "{:?} -> {:?}",
String::from_utf8_lossy(&k), String::from_utf8_lossy(&k),

View file

@ -1,6 +1,8 @@
use js_int::UInt; use js_int::UInt;
use ruma_events::{ use ruma_events::{
collections::all::RoomEvent, stripped::AnyStrippedStateEvent, EventJson, EventType, collections::all::{RoomEvent, StateEvent},
stripped::AnyStrippedStateEvent,
EventJson, EventType,
}; };
use ruma_federation_api::EventHash; use ruma_federation_api::EventHash;
use ruma_identifiers::{EventId, RoomId, UserId}; use ruma_identifiers::{EventId, RoomId, UserId};
@ -39,12 +41,12 @@ impl PduEvent {
serde_json::from_str::<EventJson<RoomEvent>>(&json).unwrap() serde_json::from_str::<EventJson<RoomEvent>>(&json).unwrap()
} }
pub fn to_stripped_state_event(&self) -> EventJson<AnyStrippedStateEvent> { pub fn to_state_event(&self) -> EventJson<StateEvent> {
// Can only fail in rare circumstances that won't ever happen here, see let json = serde_json::to_string(&self).unwrap();
// https://docs.rs/serde_json/1.0.50/serde_json/fn.to_string.html serde_json::from_str::<EventJson<StateEvent>>(&json).unwrap()
}
pub fn to_stripped_state_event(&self) -> EventJson<AnyStrippedStateEvent> {
let json = serde_json::to_string(&self).unwrap(); let json = serde_json::to_string(&self).unwrap();
// EventJson's deserialize implementation always returns `Ok(...)`
serde_json::from_str::<EventJson<AnyStrippedStateEvent>>(&json).unwrap() serde_json::from_str::<EventJson<AnyStrippedStateEvent>>(&json).unwrap()
} }
} }

View file

@ -13,18 +13,21 @@ use std::{
}; };
pub async fn request_well_known(data: &crate::Data, destination: &str) -> Option<String> { pub async fn request_well_known(data: &crate::Data, destination: &str) -> Option<String> {
let body: serde_json::Value = serde_json::from_str(&data let body: serde_json::Value = serde_json::from_str(
.reqwest_client() &data
.get(&format!( .reqwest_client()
"https://{}/.well-known/matrix/server", .get(&format!(
destination "https://{}/.well-known/matrix/server",
)) destination
.send() ))
.await .send()
.ok()? .await
.text() .ok()?
.await .text()
.ok()?).ok()?; .await
.ok()?,
)
.ok()?;
Some(body.get("m.server")?.as_str()?.to_owned()) Some(body.get("m.server")?.as_str()?.to_owned())
} }
@ -35,10 +38,11 @@ pub async fn send_request<T: Endpoint>(
) -> Option<T::Response> { ) -> Option<T::Response> {
let mut http_request: http::Request<_> = request.try_into().unwrap(); let mut http_request: http::Request<_> = request.try_into().unwrap();
let actual_destination = "https://".to_owned() + &request_well_known(data, &destination).await.unwrap_or(destination.clone() + ":8448"); let actual_destination = "https://".to_owned()
*http_request.uri_mut() = (actual_destination + T::METADATA.path) + &request_well_known(data, &destination)
.parse() .await
.unwrap(); .unwrap_or(destination.clone() + ":8448");
*http_request.uri_mut() = (actual_destination + T::METADATA.path).parse().unwrap();
let mut request_map = serde_json::Map::new(); let mut request_map = serde_json::Map::new();

View file

@ -5,10 +5,8 @@ use serde_json::{json, Value};
use std::time::Duration; use std::time::Duration;
fn setup_client() -> Client { fn setup_client() -> Client {
Database::try_remove("temp"); Database::try_remove("localhost");
let data = Data::load_or_create("temp"); let rocket = setup_rocket();
let rocket = setup_rocket(data);
Client::new(rocket).expect("valid rocket instance") Client::new(rocket).expect("valid rocket instance")
} }