mirror of
https://gitlab.com/famedly/conduit.git
synced 2024-11-19 03:10:49 +01:00
improvement: better default push rules
This commit is contained in:
parent
e7803e310a
commit
02fe030b2a
5 changed files with 359 additions and 80 deletions
|
@ -204,33 +204,7 @@ pub fn register_route(
|
||||||
&EventType::PushRules,
|
&EventType::PushRules,
|
||||||
serde_json::to_value(ruma::events::push_rules::PushRulesEvent {
|
serde_json::to_value(ruma::events::push_rules::PushRulesEvent {
|
||||||
content: ruma::events::push_rules::PushRulesEventContent {
|
content: ruma::events::push_rules::PushRulesEventContent {
|
||||||
global: ruma::events::push_rules::Ruleset {
|
global: crate::push_rules::default_pushrules(&user_id),
|
||||||
content: vec![],
|
|
||||||
override_: vec![ruma::events::push_rules::ConditionalPushRule {
|
|
||||||
actions: vec![ruma::events::push_rules::Action::DontNotify],
|
|
||||||
default: true,
|
|
||||||
enabled: false,
|
|
||||||
rule_id: ".m.rule.master".to_owned(),
|
|
||||||
conditions: vec![],
|
|
||||||
}],
|
|
||||||
room: vec![],
|
|
||||||
sender: vec![],
|
|
||||||
underride: vec![ruma::events::push_rules::ConditionalPushRule {
|
|
||||||
actions: vec![
|
|
||||||
ruma::events::push_rules::Action::Notify,
|
|
||||||
ruma::events::push_rules::Action::SetTweak(ruma::push::Tweak::Sound(
|
|
||||||
"default".to_owned(),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
default: true,
|
|
||||||
enabled: true,
|
|
||||||
rule_id: ".m.rule.message".to_owned(),
|
|
||||||
conditions: vec![ruma::events::push_rules::PushCondition::EventMatch {
|
|
||||||
key: "type".to_owned(),
|
|
||||||
pattern: "m.room.message".to_owned(),
|
|
||||||
}],
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.expect("data is valid, we just created it")
|
.expect("data is valid, we just created it")
|
||||||
|
@ -502,8 +476,7 @@ pub fn set_displayname_route(
|
||||||
displayname: body.displayname.clone(),
|
displayname: body.displayname.clone(),
|
||||||
..serde_json::from_value::<EventJson<_>>(
|
..serde_json::from_value::<EventJson<_>>(
|
||||||
db.rooms
|
db.rooms
|
||||||
.room_state(&room_id)?
|
.room_state_get(&room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::bad_database(
|
Error::bad_database(
|
||||||
"Tried to send displayname update for user not in the room.",
|
"Tried to send displayname update for user not in the room.",
|
||||||
|
@ -593,8 +566,7 @@ pub fn set_avatar_url_route(
|
||||||
avatar_url: body.avatar_url.clone(),
|
avatar_url: body.avatar_url.clone(),
|
||||||
..serde_json::from_value::<EventJson<_>>(
|
..serde_json::from_value::<EventJson<_>>(
|
||||||
db.rooms
|
db.rooms
|
||||||
.room_state(&room_id)?
|
.room_state_get(&room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::bad_database(
|
Error::bad_database(
|
||||||
"Tried to send avatar url update for user not in the room.",
|
"Tried to send avatar url update for user not in the room.",
|
||||||
|
@ -1267,8 +1239,7 @@ pub fn join_room_by_id_route(
|
||||||
|
|
||||||
let event = db
|
let event = db
|
||||||
.rooms
|
.rooms
|
||||||
.room_state(&body.room_id)?
|
.room_state_get(&body.room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
// There was no existing membership event
|
// There was no existing membership event
|
||||||
|
@ -1348,11 +1319,10 @@ pub fn leave_room_route(
|
||||||
_room_id: String,
|
_room_id: String,
|
||||||
) -> ConduitResult<leave_room::Response> {
|
) -> ConduitResult<leave_room::Response> {
|
||||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||||
let state = db.rooms.room_state(&body.room_id)?;
|
|
||||||
|
|
||||||
let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>(
|
let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>(
|
||||||
state
|
db.rooms
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
.room_state_get(&body.room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::BadState,
|
ErrorKind::BadState,
|
||||||
"Cannot leave a room you are not a member of.",
|
"Cannot leave a room you are not a member of.",
|
||||||
|
@ -1387,12 +1357,11 @@ pub fn kick_user_route(
|
||||||
_room_id: String,
|
_room_id: String,
|
||||||
) -> ConduitResult<kick_user::Response> {
|
) -> ConduitResult<kick_user::Response> {
|
||||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||||
let state = db.rooms.room_state(&body.room_id)?;
|
|
||||||
|
|
||||||
let mut event =
|
let mut event =
|
||||||
serde_json::from_value::<EventJson<ruma::events::room::member::MemberEventContent>>(
|
serde_json::from_value::<EventJson<ruma::events::room::member::MemberEventContent>>(
|
||||||
state
|
db.rooms
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
.room_state_get(&body.room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::BadState,
|
ErrorKind::BadState,
|
||||||
"Cannot kick member that's not in the room.",
|
"Cannot kick member that's not in the room.",
|
||||||
|
@ -1428,12 +1397,12 @@ pub fn ban_user_route(
|
||||||
_room_id: String,
|
_room_id: String,
|
||||||
) -> ConduitResult<ban_user::Response> {
|
) -> ConduitResult<ban_user::Response> {
|
||||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||||
let state = db.rooms.room_state(&body.room_id)?;
|
|
||||||
|
|
||||||
// TODO: reason
|
// TODO: reason
|
||||||
|
|
||||||
let event = state
|
let event = db
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
.rooms
|
||||||
|
.room_state_get(&body.room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.map_or(
|
.map_or(
|
||||||
Ok::<_, Error>(member::MemberEventContent {
|
Ok::<_, Error>(member::MemberEventContent {
|
||||||
membership: member::MembershipState::Ban,
|
membership: member::MembershipState::Ban,
|
||||||
|
@ -1475,12 +1444,11 @@ pub fn unban_user_route(
|
||||||
_room_id: String,
|
_room_id: String,
|
||||||
) -> ConduitResult<unban_user::Response> {
|
) -> ConduitResult<unban_user::Response> {
|
||||||
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||||
let state = db.rooms.room_state(&body.room_id)?;
|
|
||||||
|
|
||||||
let mut event =
|
let mut event =
|
||||||
serde_json::from_value::<EventJson<ruma::events::room::member::MemberEventContent>>(
|
serde_json::from_value::<EventJson<ruma::events::room::member::MemberEventContent>>(
|
||||||
state
|
db.rooms
|
||||||
.get(&(EventType::RoomMember, user_id.to_string()))
|
.room_state_get(&body.room_id, &EventType::RoomMember, &user_id.to_string())?
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::BadState,
|
ErrorKind::BadState,
|
||||||
"Cannot unban a user who is not banned.",
|
"Cannot unban a user who is not banned.",
|
||||||
|
@ -1642,7 +1610,8 @@ pub async fn get_public_rooms_filtered_route(
|
||||||
.map(|room_id| {
|
.map(|room_id| {
|
||||||
let room_id = room_id?;
|
let room_id = room_id?;
|
||||||
|
|
||||||
let state = db.rooms.room_state(&room_id)?;
|
// TODO: Do not load full state?
|
||||||
|
let state = db.rooms.room_state_full(&room_id)?;
|
||||||
|
|
||||||
let chunk = directory::PublicRoomsChunk {
|
let chunk = directory::PublicRoomsChunk {
|
||||||
aliases: Vec::new(),
|
aliases: Vec::new(),
|
||||||
|
@ -1775,9 +1744,29 @@ pub fn search_users_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/_matrix/client/r0/rooms/<_room_id>/members")]
|
#[get("/_matrix/client/r0/rooms/<_room_id>/members")]
|
||||||
pub fn get_member_events_route(_room_id: String) -> ConduitResult<get_member_events::Response> {
|
pub fn get_member_events_route(
|
||||||
warn!("TODO: get_member_events_route");
|
db: State<'_, Database>,
|
||||||
Ok(get_member_events::Response { chunk: Vec::new() }.into())
|
//body: Ruma<create_message_event::Request>,
|
||||||
|
_room_id: String,
|
||||||
|
) -> ConduitResult<get_member_events::Response> {
|
||||||
|
//let user_id = body.user_id.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
//if !db.rooms.is_joined(user_id, &body.room_id)? {
|
||||||
|
// return Err(Error::BadRequest(
|
||||||
|
// ErrorKind::Forbidden,
|
||||||
|
// "You don't have permission to view this room.",
|
||||||
|
// ));
|
||||||
|
//}
|
||||||
|
|
||||||
|
Ok(get_member_events::Response {
|
||||||
|
chunk: Vec::new(),/*db
|
||||||
|
.rooms
|
||||||
|
.room_state_type(&body.room_id, &EventType::RoomMember)?
|
||||||
|
.values()
|
||||||
|
.map(|pdu| pdu.to_member_event())
|
||||||
|
.collect(),*/
|
||||||
|
}
|
||||||
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/_matrix/client/r0/thirdparty/protocols")]
|
#[get("/_matrix/client/r0/thirdparty/protocols")]
|
||||||
|
@ -1951,7 +1940,7 @@ pub fn get_state_events_route(
|
||||||
Ok(get_state_events::Response {
|
Ok(get_state_events::Response {
|
||||||
room_state: db
|
room_state: db
|
||||||
.rooms
|
.rooms
|
||||||
.room_state(&body.room_id)?
|
.room_state_full(&body.room_id)?
|
||||||
.values()
|
.values()
|
||||||
.map(|pdu| pdu.to_state_event())
|
.map(|pdu| pdu.to_state_event())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -1979,10 +1968,9 @@ pub fn get_state_events_for_key_route(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = db.rooms.room_state(&body.room_id)?;
|
let event = db
|
||||||
|
.rooms
|
||||||
let event = state
|
.room_state_get(&body.room_id, &body.event_type, &body.state_key)?
|
||||||
.get(&(body.event_type.clone(), body.state_key.clone()))
|
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"State event not found.",
|
"State event not found.",
|
||||||
|
@ -2014,17 +2002,16 @@ pub fn get_state_events_for_empty_key_route(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = db.rooms.room_state(&body.room_id)?;
|
let event = db
|
||||||
|
.rooms
|
||||||
let event = state
|
.room_state_get(&body.room_id, &body.event_type, "")?
|
||||||
.get(&(body.event_type.clone(), "".to_owned()))
|
|
||||||
.ok_or(Error::BadRequest(
|
.ok_or(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
"State event not found.",
|
"State event not found.",
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
Ok(get_state_events_for_empty_key::Response {
|
Ok(get_state_events_for_empty_key::Response {
|
||||||
content: serde_json::value::to_raw_value(event)
|
content: serde_json::value::to_raw_value(&event)
|
||||||
.map_err(|_| Error::bad_database("Invalid event content in database"))?,
|
.map_err(|_| Error::bad_database("Invalid event content in database"))?,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
|
@ -2068,7 +2055,7 @@ pub fn sync_route(
|
||||||
let content = serde_json::from_value::<
|
let content = serde_json::from_value::<
|
||||||
EventJson<ruma::events::room::member::MemberEventContent>,
|
EventJson<ruma::events::room::member::MemberEventContent>,
|
||||||
>(pdu.content.clone())
|
>(pdu.content.clone())
|
||||||
.map_err(|_| Error::bad_database("Invalid PDU in database."))?
|
.expect("EventJson::from_value always works")
|
||||||
.deserialize()
|
.deserialize()
|
||||||
.map_err(|_| Error::bad_database("Invalid PDU in database."))?;
|
.map_err(|_| Error::bad_database("Invalid PDU in database."))?;
|
||||||
if content.membership == ruma::events::room::member::MembershipState::Join {
|
if content.membership == ruma::events::room::member::MembershipState::Join {
|
||||||
|
@ -2081,7 +2068,7 @@ pub fn sync_route(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = db.rooms.room_state(&room_id)?;
|
let members = db.rooms.room_state_type(&room_id, &EventType::RoomMember)?;
|
||||||
|
|
||||||
let (joined_member_count, invited_member_count, heroes) = if send_member_count {
|
let (joined_member_count, invited_member_count, heroes) = if send_member_count {
|
||||||
let joined_member_count = db.rooms.room_members(&room_id).count();
|
let joined_member_count = db.rooms.room_members(&room_id).count();
|
||||||
|
@ -2111,8 +2098,8 @@ pub fn sync_route(
|
||||||
let current_content = serde_json::from_value::<
|
let current_content = serde_json::from_value::<
|
||||||
EventJson<ruma::events::room::member::MemberEventContent>,
|
EventJson<ruma::events::room::member::MemberEventContent>,
|
||||||
>(
|
>(
|
||||||
state
|
members
|
||||||
.get(&(EventType::RoomMember, state_key.clone()))
|
.get(state_key)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Error::bad_database(
|
Error::bad_database(
|
||||||
"A user that joined once has no member event anymore.",
|
"A user that joined once has no member event anymore.",
|
||||||
|
@ -2264,7 +2251,8 @@ pub fn sync_route(
|
||||||
// TODO: state before timeline
|
// TODO: state before timeline
|
||||||
state: sync_events::State {
|
state: sync_events::State {
|
||||||
events: if joined_since_last_sync {
|
events: if joined_since_last_sync {
|
||||||
state
|
db.rooms
|
||||||
|
.room_state_full(&room_id)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, pdu)| pdu.to_state_event())
|
.map(|(_, pdu)| pdu.to_state_event())
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -2337,7 +2325,7 @@ pub fn sync_route(
|
||||||
invite_state: sync_events::InviteState {
|
invite_state: sync_events::InviteState {
|
||||||
events: db
|
events: db
|
||||||
.rooms
|
.rooms
|
||||||
.room_state(&room_id)?
|
.room_state_full(&room_id)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, pdu)| pdu.to_stripped_state_event())
|
.map(|(_, pdu)| pdu.to_stripped_state_event())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -2496,7 +2484,7 @@ pub fn get_context_route(
|
||||||
events_after,
|
events_after,
|
||||||
state: db // TODO: State at event
|
state: db // TODO: State at event
|
||||||
.rooms
|
.rooms
|
||||||
.room_state(&body.room_id)?
|
.room_state_full(&body.room_id)?
|
||||||
.values()
|
.values()
|
||||||
.map(|pdu| pdu.to_state_event())
|
.map(|pdu| pdu.to_state_event())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
|
@ -56,7 +56,10 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the full room state.
|
/// Returns the full room state.
|
||||||
pub fn room_state(&self, room_id: &RoomId) -> Result<HashMap<(EventType, String), PduEvent>> {
|
pub fn room_state_full(
|
||||||
|
&self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
) -> Result<HashMap<(EventType, String), PduEvent>> {
|
||||||
let mut hashmap = HashMap::new();
|
let mut hashmap = HashMap::new();
|
||||||
for pdu in self
|
for pdu in self
|
||||||
.roomstateid_pdu
|
.roomstateid_pdu
|
||||||
|
@ -78,6 +81,58 @@ impl Rooms {
|
||||||
Ok(hashmap)
|
Ok(hashmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the full room state.
|
||||||
|
pub fn room_state_type(
|
||||||
|
&self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
event_type: &EventType,
|
||||||
|
) -> Result<HashMap<String, PduEvent>> {
|
||||||
|
let mut prefix = room_id.to_string().as_bytes().to_vec();
|
||||||
|
prefix.push(0xff);
|
||||||
|
prefix.extend_from_slice(&event_type.to_string().as_bytes());
|
||||||
|
|
||||||
|
let mut hashmap = HashMap::new();
|
||||||
|
for pdu in self
|
||||||
|
.roomstateid_pdu
|
||||||
|
.scan_prefix(&prefix)
|
||||||
|
.values()
|
||||||
|
.map(|value| {
|
||||||
|
Ok::<_, Error>(
|
||||||
|
serde_json::from_slice::<PduEvent>(&value?)
|
||||||
|
.map_err(|_| Error::bad_database("Invalid PDU in db."))?,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let pdu = pdu?;
|
||||||
|
let state_key = pdu.state_key.clone().ok_or_else(|| {
|
||||||
|
Error::bad_database("Room state contains event without state_key.")
|
||||||
|
})?;
|
||||||
|
hashmap.insert(state_key, pdu);
|
||||||
|
}
|
||||||
|
Ok(hashmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the full room state.
|
||||||
|
pub fn room_state_get(
|
||||||
|
&self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
event_type: &EventType,
|
||||||
|
state_key: &str,
|
||||||
|
) -> Result<Option<PduEvent>> {
|
||||||
|
let mut key = room_id.to_string().as_bytes().to_vec();
|
||||||
|
key.push(0xff);
|
||||||
|
key.extend_from_slice(&event_type.to_string().as_bytes());
|
||||||
|
key.push(0xff);
|
||||||
|
key.extend_from_slice(&state_key.as_bytes());
|
||||||
|
|
||||||
|
self.roomstateid_pdu.get(&key)?.map_or(Ok(None), |value| {
|
||||||
|
Ok::<_, Error>(Some(
|
||||||
|
serde_json::from_slice::<PduEvent>(&value)
|
||||||
|
.map_err(|_| Error::bad_database("Invalid PDU in db."))?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the `count` of this pdu's id.
|
/// Returns the `count` of this pdu's id.
|
||||||
pub fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<u64>> {
|
pub fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<u64>> {
|
||||||
self.eventid_pduid
|
self.eventid_pduid
|
||||||
|
@ -212,8 +267,7 @@ impl Rooms {
|
||||||
// Is the event authorized?
|
// Is the event authorized?
|
||||||
if let Some(state_key) = &state_key {
|
if let Some(state_key) = &state_key {
|
||||||
let power_levels = self
|
let power_levels = self
|
||||||
.room_state(&room_id)?
|
.room_state_get(&room_id, &EventType::RoomPowerLevels, "")?
|
||||||
.get(&(EventType::RoomPowerLevels, "".to_owned()))
|
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
Ok::<_, Error>(power_levels::PowerLevelsEventContent {
|
Ok::<_, Error>(power_levels::PowerLevelsEventContent {
|
||||||
|
@ -244,8 +298,7 @@ impl Rooms {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let sender_membership = self
|
let sender_membership = self
|
||||||
.room_state(&room_id)?
|
.room_state_get(&room_id, &EventType::RoomMember, &sender.to_string())?
|
||||||
.get(&(EventType::RoomMember, sender.to_string()))
|
|
||||||
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| {
|
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| {
|
||||||
Ok(
|
Ok(
|
||||||
serde_json::from_value::<EventJson<member::MemberEventContent>>(
|
serde_json::from_value::<EventJson<member::MemberEventContent>>(
|
||||||
|
@ -280,8 +333,11 @@ impl Rooms {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let current_membership = self
|
let current_membership = self
|
||||||
.room_state(&room_id)?
|
.room_state_get(
|
||||||
.get(&(EventType::RoomMember, target_user_id.to_string()))
|
&room_id,
|
||||||
|
&EventType::RoomMember,
|
||||||
|
&target_user_id.to_string(),
|
||||||
|
)?
|
||||||
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| {
|
.map_or(Ok::<_, Error>(member::MembershipState::Leave), |pdu| {
|
||||||
Ok(
|
Ok(
|
||||||
serde_json::from_value::<EventJson<member::MemberEventContent>>(
|
serde_json::from_value::<EventJson<member::MemberEventContent>>(
|
||||||
|
@ -315,8 +371,7 @@ impl Rooms {
|
||||||
);
|
);
|
||||||
|
|
||||||
let join_rules =
|
let join_rules =
|
||||||
self.room_state(&room_id)?
|
self.room_state_get(&room_id, &EventType::RoomJoinRules, "")?
|
||||||
.get(&(EventType::RoomJoinRules, "".to_owned()))
|
|
||||||
.map_or(Ok::<_, Error>(join_rules::JoinRule::Public), |pdu| {
|
.map_or(Ok::<_, Error>(join_rules::JoinRule::Public), |pdu| {
|
||||||
Ok(serde_json::from_value::<
|
Ok(serde_json::from_value::<
|
||||||
EventJson<join_rules::JoinRulesEventContent>,
|
EventJson<join_rules::JoinRulesEventContent>,
|
||||||
|
@ -446,12 +501,8 @@ impl Rooms {
|
||||||
+ 1;
|
+ 1;
|
||||||
|
|
||||||
let mut unsigned = unsigned.unwrap_or_default();
|
let mut unsigned = unsigned.unwrap_or_default();
|
||||||
// TODO: Optimize this to not load the whole room state?
|
|
||||||
if let Some(state_key) = &state_key {
|
if let Some(state_key) = &state_key {
|
||||||
if let Some(prev_pdu) = self
|
if let Some(prev_pdu) = self.room_state_get(&room_id, &event_type, &state_key)? {
|
||||||
.room_state(&room_id)?
|
|
||||||
.get(&(event_type.clone(), state_key.to_owned()))
|
|
||||||
{
|
|
||||||
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
|
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#![feature(proc_macro_hygiene, decl_macro)]
|
#![feature(proc_macro_hygiene, decl_macro)]
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
|
||||||
|
pub mod push_rules;
|
||||||
|
|
||||||
mod client_server;
|
mod client_server;
|
||||||
mod database;
|
mod database;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
|
@ -4,6 +4,7 @@ use ruma::{
|
||||||
api::federation::EventHash,
|
api::federation::EventHash,
|
||||||
events::{
|
events::{
|
||||||
collections::all::{RoomEvent, StateEvent},
|
collections::all::{RoomEvent, StateEvent},
|
||||||
|
room::member::MemberEvent,
|
||||||
stripped::AnyStrippedStateEvent,
|
stripped::AnyStrippedStateEvent,
|
||||||
EventJson, EventType,
|
EventJson, EventType,
|
||||||
},
|
},
|
||||||
|
@ -95,4 +96,9 @@ impl PduEvent {
|
||||||
serde_json::from_str::<EventJson<AnyStrippedStateEvent>>(&json)
|
serde_json::from_str::<EventJson<AnyStrippedStateEvent>>(&json)
|
||||||
.expect("EventJson::from_str always works")
|
.expect("EventJson::from_str always works")
|
||||||
}
|
}
|
||||||
|
pub fn to_member_event(&self) -> EventJson<MemberEvent> {
|
||||||
|
let json = serde_json::to_string(&self).expect("PDUs are always valid");
|
||||||
|
serde_json::from_str::<EventJson<MemberEvent>>(&json)
|
||||||
|
.expect("EventJson::from_str always works")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
232
src/push_rules.rs
Normal file
232
src/push_rules.rs
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
use ruma::{
|
||||||
|
events::push_rules::{
|
||||||
|
ConditionalPushRule, PatternedPushRule, PushCondition, PushRule, Ruleset,
|
||||||
|
},
|
||||||
|
identifiers::UserId,
|
||||||
|
push::{Action, Tweak},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn default_pushrules(user_id: &UserId) -> Ruleset {
|
||||||
|
Ruleset {
|
||||||
|
content: vec![contains_user_name_rule(&user_id)],
|
||||||
|
override_: vec![
|
||||||
|
master_rule(),
|
||||||
|
suppress_notices_rule(),
|
||||||
|
invite_for_me_rule(),
|
||||||
|
member_event_rule(),
|
||||||
|
contains_display_name_rule(),
|
||||||
|
tombstone_rule(),
|
||||||
|
roomnotif_rule(),
|
||||||
|
],
|
||||||
|
room: vec![],
|
||||||
|
sender: vec![],
|
||||||
|
underride: vec![
|
||||||
|
call_rule(),
|
||||||
|
encrypted_room_one_to_one_rule(),
|
||||||
|
room_one_to_one_rule(),
|
||||||
|
message_rule(),
|
||||||
|
encrypted_rule(),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn master_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::DontNotify],
|
||||||
|
default: true,
|
||||||
|
enabled: false,
|
||||||
|
rule_id: ".m.rule.master".to_owned(),
|
||||||
|
conditions: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suppress_notices_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::DontNotify],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.suppress_notices".to_owned(),
|
||||||
|
conditions: vec![PushCondition::EventMatch {
|
||||||
|
key: "content.msgtype".to_owned(),
|
||||||
|
pattern: "m.notice".to_owned(),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invite_for_me_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![
|
||||||
|
Action::Notify,
|
||||||
|
Action::SetTweak(Tweak::Sound("default".to_owned())),
|
||||||
|
Action::SetTweak(Tweak::Highlight(false)),
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.invite_for_me".to_owned(),
|
||||||
|
conditions: vec![PushCondition::EventMatch {
|
||||||
|
key: "content.membership".to_owned(),
|
||||||
|
pattern: "m.invite".to_owned(),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn member_event_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::DontNotify],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.member_event".to_owned(),
|
||||||
|
conditions: vec![PushCondition::EventMatch {
|
||||||
|
key: "content.membership".to_owned(),
|
||||||
|
pattern: "type".to_owned(),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains_display_name_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![
|
||||||
|
Action::Notify,
|
||||||
|
Action::SetTweak(Tweak::Sound("default".to_owned())),
|
||||||
|
Action::SetTweak(Tweak::Highlight(true)),
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.contains_display_name".to_owned(),
|
||||||
|
conditions: vec![PushCondition::ContainsDisplayName],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tombstone_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(true))],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.tombstone".to_owned(),
|
||||||
|
conditions: vec![
|
||||||
|
PushCondition::EventMatch {
|
||||||
|
key: "type".to_owned(),
|
||||||
|
pattern: "m.room.tombstone".to_owned(),
|
||||||
|
},
|
||||||
|
PushCondition::EventMatch {
|
||||||
|
key: "state_key".to_owned(),
|
||||||
|
pattern: "".to_owned(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn roomnotif_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(true))],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.roomnotif".to_owned(),
|
||||||
|
conditions: vec![
|
||||||
|
PushCondition::EventMatch {
|
||||||
|
key: "content.body".to_owned(),
|
||||||
|
pattern: "@room".to_owned(),
|
||||||
|
},
|
||||||
|
PushCondition::SenderNotificationPermission {
|
||||||
|
key: "room".to_owned(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains_user_name_rule(user_id: &UserId) -> PatternedPushRule {
|
||||||
|
PatternedPushRule {
|
||||||
|
actions: vec![
|
||||||
|
Action::Notify,
|
||||||
|
Action::SetTweak(Tweak::Sound("default".to_owned())),
|
||||||
|
Action::SetTweak(Tweak::Highlight(true)),
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.contains_user_name".to_owned(),
|
||||||
|
pattern: user_id.localpart().to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![
|
||||||
|
Action::Notify,
|
||||||
|
Action::SetTweak(Tweak::Sound("ring".to_owned())),
|
||||||
|
Action::SetTweak(Tweak::Highlight(false)),
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.call".to_owned(),
|
||||||
|
conditions: vec![PushCondition::EventMatch {
|
||||||
|
key: "type".to_owned(),
|
||||||
|
pattern: "m.call.invite".to_owned(),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encrypted_room_one_to_one_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![
|
||||||
|
Action::Notify,
|
||||||
|
Action::SetTweak(Tweak::Sound("default".to_owned())),
|
||||||
|
Action::SetTweak(Tweak::Highlight(false)),
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.encrypted_room_one_to_one".to_owned(),
|
||||||
|
conditions: vec![
|
||||||
|
PushCondition::RoomMemberCount { is: "2".to_owned() },
|
||||||
|
PushCondition::EventMatch {
|
||||||
|
key: "type".to_owned(),
|
||||||
|
pattern: "m.room.encrypted".to_owned(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn room_one_to_one_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![
|
||||||
|
Action::Notify,
|
||||||
|
Action::SetTweak(Tweak::Sound("default".to_owned())),
|
||||||
|
Action::SetTweak(Tweak::Highlight(false)),
|
||||||
|
],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.room_one_to_one".to_owned(),
|
||||||
|
conditions: vec![
|
||||||
|
PushCondition::RoomMemberCount { is: "2".to_owned() },
|
||||||
|
PushCondition::EventMatch {
|
||||||
|
key: "type".to_owned(),
|
||||||
|
pattern: "m.room.message".to_owned(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(false))],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.message".to_owned(),
|
||||||
|
conditions: vec![PushCondition::EventMatch {
|
||||||
|
key: "type".to_owned(),
|
||||||
|
pattern: "m.room.message".to_owned(),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encrypted_rule() -> ConditionalPushRule {
|
||||||
|
ConditionalPushRule {
|
||||||
|
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(false))],
|
||||||
|
default: true,
|
||||||
|
enabled: true,
|
||||||
|
rule_id: ".m.rule.encrypted".to_owned(),
|
||||||
|
conditions: vec![PushCondition::EventMatch {
|
||||||
|
key: "type".to_owned(),
|
||||||
|
pattern: "m.room.encrypted".to_owned(),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue