Merge pull request 'feat: handle /publicRooms pagination' (#174) from publicrooms-pagination into master
Reviewed-on: https://git.koesters.xyz/timo/conduit/pulls/174
This commit is contained in:
		
						commit
						935f0e6185
					
				
					 1 changed files with 112 additions and 65 deletions
				
			
		|  | @ -1,12 +1,15 @@ | ||||||
| use super::State; | use super::State; | ||||||
| use crate::{ConduitResult, Database, Error, Result, Ruma}; | use crate::{ConduitResult, Database, Error, Result, Ruma}; | ||||||
| use ruma::{ | use ruma::{ | ||||||
|     api::client::r0::{ |     api::client::{ | ||||||
|         directory::{ |         error::ErrorKind, | ||||||
|             self, get_public_rooms, get_public_rooms_filtered, get_room_visibility, |         r0::{ | ||||||
|             set_room_visibility, |             directory::{ | ||||||
|  |                 self, get_public_rooms, get_public_rooms_filtered, get_room_visibility, | ||||||
|  |                 set_room_visibility, | ||||||
|  |             }, | ||||||
|  |             room, | ||||||
|         }, |         }, | ||||||
|         room, |  | ||||||
|     }, |     }, | ||||||
|     events::{ |     events::{ | ||||||
|         room::{avatar, canonical_alias, guest_access, history_visibility, name, topic}, |         room::{avatar, canonical_alias, guest_access, history_visibility, name, topic}, | ||||||
|  | @ -20,65 +23,39 @@ use rocket::{get, post, put}; | ||||||
| 
 | 
 | ||||||
| #[cfg_attr(
 | #[cfg_attr(
 | ||||||
|     feature = "conduit_bin", |     feature = "conduit_bin", | ||||||
|     get("/_matrix/client/r0/publicRooms", data = "<body>") |     post("/_matrix/client/r0/publicRooms", data = "<body>") | ||||||
| )] |  | ||||||
| pub async fn get_public_rooms_route( |  | ||||||
|     db: State<'_, Database>, |  | ||||||
|     body: Ruma<get_public_rooms::Request>, |  | ||||||
| ) -> ConduitResult<get_public_rooms::Response> { |  | ||||||
|     let Ruma { |  | ||||||
|         body: |  | ||||||
|             get_public_rooms::Request { |  | ||||||
|                 limit, |  | ||||||
|                 server, |  | ||||||
|                 since, |  | ||||||
|             }, |  | ||||||
|         sender_id, |  | ||||||
|         device_id, |  | ||||||
|         json_body, |  | ||||||
|     } = body; |  | ||||||
| 
 |  | ||||||
|     let get_public_rooms_filtered::Response { |  | ||||||
|         chunk, |  | ||||||
|         prev_batch, |  | ||||||
|         next_batch, |  | ||||||
|         total_room_count_estimate, |  | ||||||
|     } = get_public_rooms_filtered_route( |  | ||||||
|         db, |  | ||||||
|         Ruma { |  | ||||||
|             body: get_public_rooms_filtered::Request { |  | ||||||
|                 filter: None, |  | ||||||
|                 limit, |  | ||||||
|                 room_network: get_public_rooms_filtered::RoomNetwork::Matrix, |  | ||||||
|                 server, |  | ||||||
|                 since, |  | ||||||
|             }, |  | ||||||
|             sender_id, |  | ||||||
|             device_id, |  | ||||||
|             json_body, |  | ||||||
|         }, |  | ||||||
|     ) |  | ||||||
|     .await? |  | ||||||
|     .0; |  | ||||||
| 
 |  | ||||||
|     Ok(get_public_rooms::Response { |  | ||||||
|         chunk, |  | ||||||
|         prev_batch, |  | ||||||
|         next_batch, |  | ||||||
|         total_room_count_estimate, |  | ||||||
|     } |  | ||||||
|     .into()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[cfg_attr(
 |  | ||||||
|     feature = "conduit_bin", |  | ||||||
|     post("/_matrix/client/r0/publicRooms", data = "<_body>") |  | ||||||
| )] | )] | ||||||
| pub async fn get_public_rooms_filtered_route( | pub async fn get_public_rooms_filtered_route( | ||||||
|     db: State<'_, Database>, |     db: State<'_, Database>, | ||||||
|     _body: Ruma<get_public_rooms_filtered::Request>, |     body: Ruma<get_public_rooms_filtered::Request>, | ||||||
| ) -> ConduitResult<get_public_rooms_filtered::Response> { | ) -> ConduitResult<get_public_rooms_filtered::Response> { | ||||||
|     let mut chunk = |     let limit = body.limit.map_or(10, u64::from); | ||||||
|  |     let mut since = 0_u64; | ||||||
|  | 
 | ||||||
|  |     if let Some(s) = &body.since { | ||||||
|  |         let mut characters = s.chars(); | ||||||
|  |         let backwards = match characters.next() { | ||||||
|  |             Some('n') => false, | ||||||
|  |             Some('p') => true, | ||||||
|  |             _ => { | ||||||
|  |                 return Err(Error::BadRequest( | ||||||
|  |                     ErrorKind::InvalidParam, | ||||||
|  |                     "Invalid `since` token", | ||||||
|  |                 )) | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         since = characters | ||||||
|  |             .collect::<String>() | ||||||
|  |             .parse() | ||||||
|  |             .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid `since` token."))?; | ||||||
|  | 
 | ||||||
|  |         if backwards { | ||||||
|  |             since = since.saturating_sub(limit); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let mut all_rooms = | ||||||
|         db.rooms |         db.rooms | ||||||
|             .public_rooms() |             .public_rooms() | ||||||
|             .map(|room_id| { |             .map(|room_id| { | ||||||
|  | @ -190,10 +167,10 @@ pub async fn get_public_rooms_filtered_route( | ||||||
|             // We need to collect all, so we can sort by member count
 |             // We need to collect all, so we can sort by member count
 | ||||||
|             .collect::<Vec<_>>(); |             .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|     chunk.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members)); |     all_rooms.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members)); | ||||||
| 
 | 
 | ||||||
|     /* |     /* | ||||||
|     chunk.extend_from_slice( |     all_rooms.extend_from_slice( | ||||||
|         &server_server::send_request( |         &server_server::send_request( | ||||||
|             &db, |             &db, | ||||||
|             "privacytools.io".to_owned(), |             "privacytools.io".to_owned(), | ||||||
|  | @ -212,17 +189,87 @@ pub async fn get_public_rooms_filtered_route( | ||||||
|     ); |     ); | ||||||
|     */ |     */ | ||||||
| 
 | 
 | ||||||
|     let total_room_count_estimate = (chunk.len() as u32).into(); |     let total_room_count_estimate = (all_rooms.len() as u32).into(); | ||||||
|  | 
 | ||||||
|  |     let chunk = all_rooms | ||||||
|  |         .into_iter() | ||||||
|  |         .skip(since as usize) | ||||||
|  |         .take(limit as usize) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|  |     let prev_batch = if since == 0 { | ||||||
|  |         None | ||||||
|  |     } else { | ||||||
|  |         Some(format!("p{}", since)) | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let next_batch = if chunk.len() < limit as usize { | ||||||
|  |         None | ||||||
|  |     } else { | ||||||
|  |         Some(format!("n{}", since + limit)) | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     Ok(get_public_rooms_filtered::Response { |     Ok(get_public_rooms_filtered::Response { | ||||||
|         chunk, |         chunk, | ||||||
|         prev_batch: None, |         prev_batch, | ||||||
|         next_batch: None, |         next_batch, | ||||||
|         total_room_count_estimate: Some(total_room_count_estimate), |         total_room_count_estimate: Some(total_room_count_estimate), | ||||||
|     } |     } | ||||||
|     .into()) |     .into()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[cfg_attr(
 | ||||||
|  |     feature = "conduit_bin", | ||||||
|  |     get("/_matrix/client/r0/publicRooms", data = "<body>") | ||||||
|  | )] | ||||||
|  | pub async fn get_public_rooms_route( | ||||||
|  |     db: State<'_, Database>, | ||||||
|  |     body: Ruma<get_public_rooms::Request>, | ||||||
|  | ) -> ConduitResult<get_public_rooms::Response> { | ||||||
|  |     let Ruma { | ||||||
|  |         body: | ||||||
|  |             get_public_rooms::Request { | ||||||
|  |                 limit, | ||||||
|  |                 server, | ||||||
|  |                 since, | ||||||
|  |             }, | ||||||
|  |         sender_id, | ||||||
|  |         device_id, | ||||||
|  |         json_body, | ||||||
|  |     } = body; | ||||||
|  | 
 | ||||||
|  |     let get_public_rooms_filtered::Response { | ||||||
|  |         chunk, | ||||||
|  |         prev_batch, | ||||||
|  |         next_batch, | ||||||
|  |         total_room_count_estimate, | ||||||
|  |     } = get_public_rooms_filtered_route( | ||||||
|  |         db, | ||||||
|  |         Ruma { | ||||||
|  |             body: get_public_rooms_filtered::Request { | ||||||
|  |                 filter: None, | ||||||
|  |                 limit, | ||||||
|  |                 room_network: get_public_rooms_filtered::RoomNetwork::Matrix, | ||||||
|  |                 server, | ||||||
|  |                 since, | ||||||
|  |             }, | ||||||
|  |             sender_id, | ||||||
|  |             device_id, | ||||||
|  |             json_body, | ||||||
|  |         }, | ||||||
|  |     ) | ||||||
|  |     .await? | ||||||
|  |     .0; | ||||||
|  | 
 | ||||||
|  |     Ok(get_public_rooms::Response { | ||||||
|  |         chunk, | ||||||
|  |         prev_batch, | ||||||
|  |         next_batch, | ||||||
|  |         total_room_count_estimate, | ||||||
|  |     } | ||||||
|  |     .into()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[cfg_attr(
 | #[cfg_attr(
 | ||||||
|     feature = "conduit_bin", |     feature = "conduit_bin", | ||||||
|     put("/_matrix/client/r0/directory/list/room/<_>", data = "<body>") |     put("/_matrix/client/r0/directory/list/room/<_>", data = "<body>") | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue